Creating a White-Label Mobile Application
Who This Is For
In this article, I am going to explore existing approaches to white-label mobile application development. It’s not overly technical — you won’t find code examples or the specifics of any platform in it — however, you will meet concepts like the backend, frontend, code repositories, and application architecture. This article might be helpful for engineering managers, chief technology officers, and software developers who want to broaden their knowledge. It might also be helpful for product managers looking to understand the technical decision-making process better.
What Is App White Labeling?
“White labeling” is a term that denotes a certain type of product across verticals. It comes from the music industry: In the 1970s, promo records were distributed in small quantities and had no official branding yet. Instead, they came with disk-shaped white labels covering the center of the record. Today, when something is said to be “white label,” it means you can buy it and release it under your own brand name.
If you’re reading this article, I assume you know what white labeling is. Moreover, you probably know there are different kinds of white-label applications. I’m not going to give a general overview of all of them because there are plenty of great articles on the internet that already do that. Instead, I want to focus on the architectural and technical approaches to building white-label mobile apps — specifically how to choose a technical approach based on your business model. Spoiler alert: Your software architecture will and should follow the model and constraints of your business.
Where to Start
The first thing you want to figure out before starting your app is the level of customization you want to give your customers. Let’s imagine a spectrum. On the left hand side, users can have little to no customization. Essentially you allow them to choose a font color, and that’s about it. On the opposite side is the approach with maximum customization: When a new customer comes, you would create a full-on duplicate of the “master” app for them. However, you need to be aware that each dimension of customization will increase the cost of developing and maintaining our app.
Each move from left to right on our spectrum will have a price. To figure out where our app will be on this spectrum, we have to ask about the kind of customization our customers expect:
- Do they want to have a separate app in the App Store/Play Store?
- Could customers ask for a different screen layout?
- Should they have different navigation menus?
- Do we allow for configuration with custom features and modules?
We must also decide whether we are ready to pay for this customization.
Why is it important to know where your app is on the customization spectrum? There are many approaches to developing a white-label app. Each has its benefits, but generally, they can be reliably placed on our customization-cost spectrum. It doesn’t make sense to choose the architecture from the right side of the spectrum when you want your app to be on the left.
Note that the app’s position on the customization spectrum is not static. Over time, your customers may ask for more customization, and you might slowly traverse to the right — giving them more freedom but at a higher maintenance cost. Or, vice versa, you may decide to reduce costs to attract more clients who don’t want to pay extra for custom screen layouts. It’s reasonable not to provide too many customization options from the get-go as you learn your customer base, but you should know how your architecture will evolve down the line.
A Note on Server Architecture
Before digging into mobile app development overview, it’s worth saying a few words about the server architecture. When it comes to mobile applications, there are multi-tenant and single-tenant server architectures.
A multi-tenant server uses the same code, infrastructure, and database for multiple tenants, or clients. This is typical of SaaS applications. Tenants don’t have access to one another’s data, but they are “living in the same house.” The main advantage of this approach is reduced cost. It’s cheaper to build, test, and maintain because every tenant has access to the same features, meaning bugs are fixed for everyone at once. The disadvantage, though, is that it limits the level of potential customization for each tenant.
On the other hand, with a single-tenant architecture, each tenant has its own copy of the server. They might come from the same codebase, but they will “live” independently. The single-tenant backend is used mainly for highly customizable white-label apps that are closer to regular custom apps.
The multi-tenant server is a much more popular choice. With some architectural decisions, like modular architecture, you can even provide different backend capabilities for tenants. I’ll use a multi-tenant backend in my upcoming examples.
Now let’s look at different approaches to developing white-label mobile apps. They’re named in an arbitrary fashion, so as to reflect the gist of each particular approach.
1. Container Application
Best Suitable For:
Applications that require the fastest and cheapest onboarding of new clients, preferably without the involvement of the development team. For example, companion applications for conferences or educational platforms for individual tutors.
The main antagonist of the 2016 movie Split had dissociative identity disorder. He had 23 alter-egos — separate personalities that could each take control of his body. Only one personality could be active at a time, and the other 22 would be dormant. This is a weird but surprisingly close analogy that can help explain the Container Application approach to white labeling.
With this approach, you’ll have a single host application that can transform itself into any client’s application, usually by “disguising” itself in the client’s colors and branding. This application will be distributed under a “neutral” brand in the App Store or the Play Store. At some point, usually after the user logs in, the app will receive the information about which clients it should represent, and it will change its appearance.
- This is the closest architecture to the regular application. It is, in essence, a single application, but with the ability to slightly change its appearance.
- Very straightforward release management — you need to publish and update only one application.
- Each client is always using the same version of the backend.
- This approach opens up the possibility of onboarding new clients without any development effort. If the client theme and metadata are stored on the server, they can be delivered to the application after the user logs in.
- Client Migration to a Separate Application: Some clients may decide that they don’t want to share the application with anyone else anymore.
- Mitigation: Keep the code, which will be common for multi-tenant and single-tenant applications, in a separate module.
- Data Security and Privacy: There is potential risk of data leakage between clients because every client is using the same — literally — application.
- Mitigation: Avoid keeping client-specific information in the codebase. The client’s data should be delivered from the backend after successful authentication. Ensure implementation of data-based security on the backend API level. There should be no way one client could get data from another client from the backend.
- Large Application Size: Because the application will carry the resources needed to transform to ANY client application, the application bundle size might be getting out of control.
- Mitigation: Load the client’s resources and assets from the server on demand.
- “Frankenstein” Application: Some clients might want unique features. A feature here, a feature there, and the application might become an unmanageable monster stitched from parts of unrelated applications.
- Mitigation: Move clients with unique features to a separate application. Extract shared code as a separate dependency for container application and unique client application.
2. Single-Tenant Application with Custom Theme
Best Suitable For:
Applications that require fast and cheap client onboarding, but clients want to have their own application in the app stores. For example, applications for small-to-medium food chains and restaurants.
With this approach, each client will have its own application and the ability to create a custom UI theme. It can be a custom logo, colors, fonts, background pictures, etc. Page layout, forms, and navigation — essentially the skeleton of the application — will be the same for each client.
Even though client applications will appear as independent in the App Store/Play Store, they will share as much code as possible. For applications with customizable themes, we’re talking about 99% of shared code. Notice that I used the word “shared,” not “similar” — we’re not copying code when creating an application for a new client. In practice, the shared code will sit in some common module, and each client application will have a dependency on that common code. For example, if you have three clients, you will have at least four modules: one module with common code and three modules for each customer’s application. Ideally, application modules won’t have any code at all. They’ll just have some kind of declarative configuration for your common code that will set up the theme — the band name, logo, colors, etc.
- Separate applications for each client in the app stores
- Relatively low cost of maintenance
- Relatively low cost of onboarding new clients
- A flexible strategy of adding more customization — common code could be split into more fine-grained and configurable building blocks.
- Deployment Complexity: Deployment of multiple applications that depend on the shared modules might lead to errors and confusion about what code is now deployed.
- Mitigation: Introduce a solid CI (continuous integration) system and automated deployments.
- Inter-Client Dependencies: Client-specific code might leak into common modules, leading to a fragile system where change for one client breaks another client’s application.
- Mitigation: Modules decoupling strategy and strong dependency discipline — common code shouldn’t depend on or be aware of any client applications. Client applications shouldn’t depend on one another.
- “Favorite” Clients: Developers might choose the “default” client application and only work with that, rarely paying attention to other client applications.
- Mitigation: Create a “neutral” application and do most of the development and testing on this application. Also develop a proper regression testing procedure for client applications.
- QA Overload: Although client applications share a lot of code, for the QA team, those applications are separate and should be tested independently. This could lead to a disproportionate increase in workload for the QA team.
- Mitigation: Introduce an automated QA process.
- Fast and Slow Clients: Some clients might want features that will require backward-incompatible changes in common modules. Those changes will require you to update all client applications.
- Mitigation: Introduce a module versioning system.
3. Single-Tenant Application with Customizable Layout
Best Suitable For:
Applications for enterprise clients who want their apps to have a more unique look and feel. For example, platforms for corporate learning.
With this kind of application, we’re on a slippery slope. We’re now allowing customers to change the layout of the screens, navigation, transitions, and workflow. If we’re not careful and smart, we could be on the steady path to multiplying the maintenance cost for our applications over time.
Customizable Layout is often seen as the next evolutionary step of the Customizably Themed application. The code organization looks similar, but it has some additions. Here are the components:
- Client Application: As in the previous example in approach #2, this component aggregates and depends on other components. This component will build a final application. In the client application, you only want to have that, which makes it different from other client apps. E.g., configuration, metadata files, assets — any declarative way to configure other components.
- Business Logic: Sometimes developers call this component the “core.” This is your application, but it’s stripped of any specifics of visual representation. For example, your application might have a “Buy” button. Clicking it should trigger a chain of events. Some are related to the UI, like changing the button’s color or opening another screen — but others are not, like sending the request to the backend or saving some data on the device. Those should go to the Business Logic, or Core. A good rule is to ask yourself, “If I move this button to another screen, which part of the code will stay the same?” The answer will most likely belong to the Business Logic. The code in the Core should not be aware of its existence or have a dependency on other components.
- Components Library: While you allow clients to have custom pages and screens, it’s unlikely they will be completely unique. They will share some UI blocks, such as forms, views, or even entire screens. They might be themed, but fundamentally, they will stay the same across clients. It makes sense to have those UI blocks in a separate module. The application’s UI will be built from the building blocks in this component. The components are usually “dumb,” meaning they don’t have any logic in them. They don’t know about other modules and are expected to be configured from the outside.
- Layout Controller: This component has a similar role to the “controller” in the MVC pattern. It stitches together UI components from the Components Library. It contains rules of communication between the UI components and screens, and connects the UI representation with the Business Logic. All of it is done according to the configuration that a specific client application provides. Client applications usually don’t use the Component Library directly, although they might use Business Logic.
- The ability to make things highly customized
- Controlled maintenance costs
- Testable UI — Although UI can be changed, it’s essentially predictable and static for each client and can be reliably tested across devices.
Risks are similar to those of the Custom Theme approach with some additions:
- Bulky Layout Configurations: Layout configuration might become too big and complex. Clients might have a lot of copy-pasted configuration code.
- Mitigation: Add higher-order components. For example, create a standard “Purchase” form instead of having each client build it from individual fields and buttons.
- Slow Regression Testing: An increased amount of UI layout combinations might create a lot of work for the QA team and add time to pre-release testing.
- Mitigation: Invest in automated integration testing.
4. Backend-Driven UI
Best Suitable For:
Applications that require frequent and immediate updates of UI for all users. For example, retail applications that need to change UI based on current promotions.
Backend-Driven UI (or backend-driven development or server-driven UI) is a mobile development concept in which the UI layout, screens, transitions, and content are controlled by the backend. In this concept, the backend not only stores the data but also controls how the mobile application will render its screens.
The mobile application will be asking for some kind of metadata from the backend before rendering the screen. Such metadata will give clear instructions on how this screen should be rendered. For example, metadata might look like this:
In response, the application will render something like this:
This approach offers a lot of flexibility because you can choose how much control to give to the backend. It’s even hard to pinpoint where exactly this architecture should sit on our customization spectrum, because it really depends on the implementation. In any case, this approach requires a sizable investment in the backend infrastructure. In exchange, though, it offers a very unique feature: the ability to update app UI without going through the App Store/Play Store release process. This can be crucial for retail-type applications because they need the ability to put up promo banners quickly.
Backend-Driven UI Architecture Overview
The main difference from the Application with Customizable Layout is in the Layout Controller component. This component will need to communicate with the server. Putting the server communication code into the Business Logic will be tempting, but I suggest not to mix it with data-related server calls. The business Logic and Components Library will fundamentally stay the same.
For this architecture to work, you will need a solid backend infrastructure. Your backend will have a separate API to serve a layout configuration. It makes sense to consider a separate backend-for-frontend and not mix it with the “main” data backend. Moreover, you probably need a web-based editor to represent the mobile layout visually.
- The ability to update UI without going through the release phase
- Outstanding customization capabilities
- The ability to quickly perform A/B testing
- Reduced amount of mobile UI development
- Testing Overhead: As is the case with the Customizable Layout approach, dynamic layout creates an ever-expanding amount of UI screens that should be tested. With the backend-driven UI, having a finite list of UI component combinations is impossible because clients can change them in runtime. This could create an inadequate load on a QA team.
- Mitigation: Invest in integration and end-to-end automated tests, analyze existing UI layout, and create a chart of top UI layout combinations that should be tested.
- Offline Rendering: The application relies on stable internet connection for rendering, which is not always possible.
- Mitigation: Fallback strategies for offline rendering; caching mechanisms
- Hidden Maintenance Costs: The backend-driven UI approach usually minimizes mobile development effort. But this effort doesn’t disappear — it moves to the backend, frontend, infrastructure, and QA teams.
- Mitigation: Add complete development team effort when estimating the total cost of ownership of mobile features.
- Performance Issues: Clients might create layout combinations that are too heavy for the application and negatively impact performance.
- Mitigation: Conduct regular performance testing, and create adequate limitations and constraints for UI layout.
- Security Concerns: There is a risk of injection attack because the backend can send and control much more in the mobile application.
- Mitigation: Regular security audits, robust backend input validation, limitation of what backend can control and its impact in mobile application — for example, you don’t want to send any executable code to the mobile application.
5. Modular Architecture
Best Suitable For:
Applications with a flexible pricing model that depends on different feature packages. For example, fleet management applications.
In the previous approaches, we only allowed customizations on the UI level. But what if our clients want a custom Business Logic? What if we want to enable our clients to include or exclude entire features? This is where modular architecture can be helpful.
Modular architecture is a technique in which we split our application into self-sufficient, independent modules. Each module can contain all components of the application: business logic, communication with the server, UI components, etc. This concept is not unique to white-label development or mobile application design. A good example of a modular application is any modern IDE (integrated development environment). It lets users enable or install different plugins and modules. Each of them adds new capabilities to the application and changes the UI.
Modular architecture is a very broad topic — so broad that a detailed overview would be out of the scope of this article. So, I want to outline some of the main concepts that will hopefully help you understand the nature of modular architecture:
- Common Protocols: The core of your application is the carrier for all the modules. It should define all common protocols, interfaces, and extension points. For example, it can define an interface for modules to get information about logged-in users. Or, it can define an extension point for modules to add new items to the main navigation menu.
- Module as an Add-On: Each module is an addition to the Core application. Ideally it should add capabilities, not change or remove existing ones.
- Modules Are Independent: You want to have modules as independent from one another as possible. There are techniques for creating manageable inter-module dependencies — for example, module interface — but they can quickly get out of control.
- Modules Are Optional: Each module is an optional addition. The core application should be self-sufficient with zero modules and shouldn’t know the specifics of any module. If your Core application requires some modules to run properly, consider including the functionality of this module in the Core application.
- The ability to create flexible pricing models that can fit a broader group of clients
- Isolation of changes: Updates in the module’s code won’t affect the entire application.
- An excellent way to manage large applications
- Dependency Hell: There is a risk of creating complex and fragile dependency schemes between modules and the core application.
- Mitigation: Avoid inter-module dependencies. If an inter-module dependency is required, avoid circular inter-module dependencies.
- Integration Issues: While modules are loosely coupled, they can create conflicts and issues when used together.
- Mitigation: Invest in automated integration testing, and add integration test cases to the test plan.
- Security Concerns: External modules and add-ons can inject harmful code into the core application.
- Mitigation: Review core application protocols, interfaces, and extension points from a security perspective.
In the world of white-label mobile application development, it might feel like you’re trying to juggle 10 clubs . . . while riding a unicycle . . . while on fire. On the one hand, each new feature, each new customization dimension, and each new client adds another entity to worry about and maintain. Without focus and discipline, it can get out of hand very quickly and bury your operations and development under constant firefighting activities.
On the other hand, you want to have new clients, give them new features, and have a competitive edge. It’s a delicate balance.
The good news is that there are a lot of approaches, strategies, and tools that can help you find this balance. The architectures presented in this article are just the tip of the iceberg. There are many more — some of which don’t even have a name. You don’t have to stick to any of them, so you can combine ideas from different approaches and come up with your own. A good strategy is to look around and find an approach that fits your situation today. Then, think about how to take a step forward for more flexibility. Proceed one step at a time.
with ObjectStyleSee our work