A recent client asked our team to revisit and white label a product for additional customers. The application manages business in a low-tech industry where most finance and accounting is controlled with endless spreadsheets. The client successfully doubled their capacity through the use of the application and noticed other businesses in the industry could benefit from a similar piece of technology.
So, you wanna white-label?
White labeling was originally a term used for when a musical artist would send out their new record in a white sleeve before album artwork was completed, hoping to garner hype and promotion in the clubs before the true release date. A more intuitive example would be a cereal manufacturer selling a generic box of corn flakes to Sam’s Club and Target and letting each store brand the item themselves. That’s why there is a real product out there named “Square Shaped Corn”.
Here’s a synopsis of how the original software had to change:
There are a few options for how to design a multi-tenant application 1) separate database 2) shared database with separate schema or 3) shared database with shared schema. This paper can provide many more details on the differences and tradeoffs. We chose option 3, which has the lowest hardware and devops costs, but higher concern around security, permissioning, and modularity.
For example, one page depicts the payment history, and is used by the client to cross reference with some bank software to confirm amounts. The ID of each record is displayed. As new payments are entered, the records are added to the database, with each ID incrementing by exactly 1. Moving to a shared database meant that the order of the IDs would not be preserved. One user can have payment IDs of 101, 102, and 103, and then another user could interrupt the sequence and grab ID 104. Later down the road when the first user goes to audit the payments, suddenly payment 104 would be missing. This is a reasonable refactor when compared to hosting another database.
Security and Permissions
Because this is a Rails application, we had some solid options for how to handle data security for the shared database. I’ve used both Pundit and CanCanCan as a permissioning library. Our preference changes from time to time but we went with Pundit on this application because of the better structure (each model/controller gets its own policy file) and the built-in scope builder. It was easy to manage multiple tenant security without a lot of DevOps work due to the shared database / shared schema design decision.
For every spec involving data querying, a new spec had to be written to ensure no data would leak across the different tenants. Same for integration specs. The suite increased in size by ~50% without a single new feature, one of the downsides of a shared database / shared schema design.
Much of the config settings had to change in order to accommodate additional tenants. A few different techniques were used:
- Move things from the singleton AppSettings to a new class and table: ex. bank account information
- Move things from an environment variable to the database: ex. email account to BCC on all payment receipts
- Introduce a new variable or database field: ex. original system had assumptions for a task to run at 5 pm, but the new tenant required a different time
- No change required: ex. email system sender
There’s a range of how far you can take the design of a white label product. On one end you can allow each tenant to choose a full color palette and the layout of the main pages (hard). On the other, you can simply wipe anything related to the original tenant and let each new tenant upload a logo for the navigation bar (easy). The client opted for a full redesign with little customization beyond a logo and new domain… anything is better than the spreadsheet hacking they were used to.
Whenever you start to move things around to look better, you start to question the deeper implications of layout and workflow. This shed light on the fact the application might not be as intuitive as it could be. So in addition to design, there was a lot of value in rethinking the user experience of some major parts of the application.
So, you wanna white label? Be prepared to rethink the core functionality of the application. For simplicity, imagine the original application was used by one person (our client). With a single user, usability is not thoroughly tested. Once that user understands how to use the product, that’s it. Even if they use it in an inefficient manner, the user will always know that you do that one thing by clicking on that one button.
While developing a multiuser system, we invested a lot of resources into making sure the next user also had a good experience. The redesign did help here, specifically on a page where the user sets up a matrix of complex business terms and processes.
After onboarding a second tenant, we feel more comfortable that our UX is improved. But we won’t know if it is right until there is a third, fourth, fifth… and hundreth tenant.
Meeting Requirements Without Meeting the User
There is no way to avoid custom one-off features. We built a strange disclosure statement for a regulatory agency in the state of North Carolina. Our client does business only in Illinois. But the second tenant would stand to gain a lot from this feature. How do you meet the requirements without meeting the user? Our team built and iterated on this feature, but ultimately we didn’t receive user feedback and cannot know for certain that the feature is adequate. To improve our process, we should have directly contacted the tenant in North Carolina for a brief meeting to gather requirements, rather than communicating via email through the client.
Business Is Not Logical
We throw out the term “business logic” often in software to describe how a business operates in technical terms. But a business does not operate how the computer wants it to behave. There are handshake deals, give-and-take negotiations, manual adjustments, and many “owe you one” customers.
Do we design the software to cover every edge case of doing business? No! Having more tenants on the application required additional versatility overall. Complexity increases with each new business practice implementation, and it is not feasible or recommended to include every one when white-labeling.
When solving a business or software problem, I often like to think in terms of alternatives and the tradeoffs associated with each. This process was crucial for white labeling. Generalizing a complex business product for use by multiple tenants required hard choices in design, usability, and app code. So, if you wanna white label… be ready for tradeoffs and don’t expect to just jam some new tenants into your product. This project was technically intriguing, often including full refactors of the original code. It was also an excellent consulting experience, with complex decision making and communication obstacles throughout. Shoutout to everyone who worked on the original product, the white labeling project, and anyone who has tried dynamically watermarking PDFs with logos from different tenants…