Originally posted on the Plum Engineering Blog

At Plum we use a few internal tools to help our engineers debug issues faster.

Our mobile apps also have some internal tooling that we place in a view controller called The Batcave. The Batcave is only accessible on our internal builds and is there to aid in debugging and testing.

Our last blog post explains our build and release process.

This post is a little sneak peak into the Batcave…


Our data models are very state heavy. There are states ranging from the users transactions state: pending, failed, successful etc. The state of a users investment onboarding flow: pending, completed, data required etc. Also, Let us not forget the state of the connection to the users bank account which can hold many wonderful combinations of state.

Our apps use these states to determine what UI to show and how to show it.

Being able to understand what is being shown to the user and why, is really important when debugging.

So we built a very non-intrusive HTTP debugging library that gives us the ability to inspect all requests and responses on the device.

We then took it one step further and added a “Report a bug” button to the Batcave. Tapping this will zip up the last 30 request and responses and present a MFMailComposeViewController with a bug report template and a zip file of all the data attached. The email is sent to Zapier where it is then processed and turned into a Jira ticket 🎉

Having this type of tooling helps to tighten the loop between finding, debugging and fixing bugs.


No Batcave would be complete without the ability to select which server the app points towards. However, just being able to point to production or staging wasn’t enough. We needed our backend engineers to be able to easily test the Plum app against their own local version of Plum’s backend.

Inside the Batcave, along with the options for selecting the predefined servers there is the option for assigning a custom server. There are four text fields for the four base urls that the app needs to function. This is quite a lot of typing and prone to error so we added a QR code scanner that can be used to simply pass a predefined JSON payload containing all the data required to the Batcave.

View Controller Presentation

We have quite a few view controllers that aren’t directly accessible from the main navigation of the app, like splash screens, onboarding flows and our KYC flow.

It important we can access these screens easily for testing and demoing so we built a simple list that lets us present these screens whenever we want.

Open Sourcing Spinosa

We finish this post with a little gifts. Several months ago we open sourced our CardNavigationController library and today we’re open sourcing Spinosa the HTTP debugging library we use in Plum. Enjoy!

We’re Hiring

P.S. You should totally join us.