Close Menu
    Facebook X (Twitter) Instagram
    • Contact Us
    • About Us
    • Write For Us
    • Guest Post
    • Privacy Policy
    • Terms of Service
    Metapress
    • News
    • Technology
    • Business
    • Entertainment
    • Science / Health
    • Travel
    Metapress

    Behind the Scenes of White Label Android App Development: Interview with Dmitry Nikitin

    Lakisha DavisBy Lakisha DavisJuly 14, 2024Updated:June 23, 2025
    Facebook Twitter Pinterest LinkedIn Tumblr Email
    Behind the Scenes of White Label Android App Development: Interview with Dmitry Nikitin
    Share
    Facebook Twitter LinkedIn Pinterest Email

    Dmitry Nikitin is an experienced Android software engineer with big projects at Yandex Mail, Tinkoff, Kolesa.kz, Money Supermarket, and Russian Post under his belt. Now Team Leader at Quadcode, he is in charge of both the Android team and the cross-functional Clients Branding team, for which he designed a multi-module project that now serves dozens of brands. Through his time, the team reduced application regression time from 5 to a mere 1 day in building a robust white-label system spanning Android, iOS, Desktop, and Web platforms. Dmitry sat down with us to tell a real story of scaling white-label architecture:  the struggles, fixes, and hard-earned lessons learned in handling tens of custom-branded brands.

    Dmitry, let’s start with the basics. What is white-label and why do companies need it?

    White-labeling refers to a process when a company makes a product and another company resells it under their own brand name. It’s convenient for every party involved: the customer gets a ready-made mobile app adapted to their visual identity and functional requirements, but doesn’t spend a penny on R&D from the ground up. It’s crucial when you need to hit the market quickly but still be recognizable.

    I bet not everything went perfectly from the start. How was the white-label approach implemented in your case?

    White-labeling doesn’t occur overnight. We started off with a B2C product that had no scaling requirements whatsoever. Then the first B2B client appeared, and all hell broke loose. There was zero customization of any sort to start with, so we just swapped icons and logos here and there.

    Then all the requests started pouring in: “Can we have our own authorization portal?”,
    “Can we have a different billing system?” and so on. And it soon became clear that without a multi-modular architecture, a versatile system of design and flexible CI/CD, we would not get very far.

    What did the architecture evolution look like for this?

    It started before B2B for us. We had our own in-house solutions, and at some point, it became clear that we needed to recycle bits of functionality between them. So we started breaking up the monolith earlier, just to not duplicate things.

    Once the B2B direction emerged, this became absolutely essential as every single new brand had its own set of needs, which meant the architecture had to be able to change quickly. We started actively transferring the functionality to standalone modules, and there were over a hundred of them soon. There are over one hundred fifty now. Everything is organized by internal rules: what can be overridden, how the custom implementations are connected, how business logic is separated.

    We didn’t build some über-complicated system. Everything was evolutionary. The trick was to separate where we have the core and where the “variable parts” are, and design it in such a manner that one thing could be altered without another being broken.

    There were probably difficulties with the visual part too. How did you solve the interface customization task?

    This was a quest on its own. We started by extracting everything hardcoded: colors, dimensions, icons and anything that made it difficult to change appearances flexibly. Then we transferred this into its own “palette”, or a group of values that were already present within the project. At the very least, this simplified switching between themes.

    Then the more profound changes began. We replaced all raster icons with vector ones, but not for fashion’s sake. Vector icons are easy to recolor, and they take the same tokens as the rest of the UI. This move alone significantly simplified theming support.

    Then the contextual palette arrived. We introduced abstract tokens such as “surface color”, “main text”, “secondary action icon” and so forth. They adapt to the theme, platform, and background.

    In order to port a gigantic existing project to this new framework, we first tried the route of automatic replacement. To put it simply, we grabbed the old values and looked for the nearest new tokens by meaning. But that didn’t quite work out: some replacements worked as planned, and others had weird effects.

    With time, we got better at this, until we ran into brand new pitfalls. For example, an icon token had the same color as a text token, and in the previous code version, text started behaving like an icon out of nowhere. We had to resolve such conflicts manually.

    Then there was the realization that one contextual palette wasn’t enough. One client, for example, wanted only one specific button to be white on black background in a dark theme. Context can’t do that because it doesn’t know that this is exactly that button.

    That’s why we invented component tokens. They were added initially point-wise, for a specific task or component. Step by step, we’ve developed a full palette. Now any screen can be assembled from scratch with the ability to flexibly tailor elements out of the box, without breaking system logic.

    How do you synchronize with the client on appearance? So that in the end you get exactly what they had in mind?

    We added a visual preview right in the admin panel. The client chooses color scheme, fonts, interface elements and immediately sees how it will look on Android, iOS and the web. I think of it as a vector-based building block set. All elements rely on the same tokens as the real application. These vectors are exported from Figma directly, not just as pretty graphics, but as fully implemented parts of our system.

    This is a very old pain point. Previously, the customer would bring us a mockup, and we’d say it’s not going to work that way. The logic’s different, everything will break. With a complex product, you can’t just take and change one screen, as there is always a stack of states, dependencies and interactions behind it.

    How did you organize release management with so many brands and frequent changes? Surely not everything was smooth from the beginning.

    It was painful. At first, we took the classic, tried and tested approach: one feature branch per feature, then manual testing, then merge after QA approval. This approach worked well with a few customers.

    Everything started to cave like a house of cards when the business started growing. One branch is waiting for release, another one is blocking the third one, and the third one is outdated waiting in a queue. Permanent conflicts and cascade regressions appeared.

    By the way, one of the things that saved us more than once is feature toggling, which we’ve had from the very beginning. But it’s not a silver bullet. Even if a feature is switched off, this doesn’t guarantee its code won’t hit anything vital, especially in a complex, interdependent system. Somewhere along this way it became evident that either we remake processes, or we will suffocate. To that end, we switched to Trunk-Based Development. Now we integrate all changes in the main branch in small and often increments.

    We made unit tests mandatory for any new feature, which we had only employed before for relative “peace of mind”. Now it’s a rule of law: if the critical path isn’t covered, it doesn’t go into the trunk. We expanded the base of integration tests, added UI scenarios that run on every pull request. As well as nightly runs to catch regressions early. And only then did the trunk really become stable.

    But development is one thing. Releases are another. Releasing updates “for any reason” simply didn’t work: full regression testing, even with a good level of automation, still takes time. And the more time we spend on regression,  the less we manage to do new things.

    So now we have two strategies:

    • Regular releases, when we test the entire application and deploy a batch of brands together.
    • On-demand releases for the specific client request, with minimal changes.

    Let’s say, we take tag 1.0.0, add there the fix we need, and make 1.0.1 release. But all the changes first come through the trunk. No matter how much you’d want to just commit the fix to the release branch, there’s just no way to do that. If you forget to merge it back to trunk, then hell breaks loose. If you’ll do everything from trunk, you can remain confident that the entire release is tested, and the quantity of untested code is minimal.

    So we can have both a quick response to customer needs and maintain the stability. But the path to this approach was a long one through suffering, chaos and midnight rollbacks.

    How do you verify that everything works correctly, especially when there are already many brands and each is customized in its own way?

    We could not do that without automation. When you have dozens of brands and each one can be different,  even if only in fonts or buttons colors, manual testing soon becomes a dead-end.

    Therefore, we started to build a UI test framework that takes into account the entire brand context: logos, names, colors, icons,  all of this is passed to separate configurations. For any test, you can specify under which brand it is running. We use Kaspresso: it helps to run scenarios and check interface behavior under the right conditions.

    We also have a test library that creates the “right” user. Want to test a page for an already authenticated client? No problem. Same with a user who started registration but never finished the process. All the states can be established without having to manually
    click through” each scenario. This saves us tons of time and also eliminates bugs that would only occur on the client side.

    What would you advise a team that’s just starting to work with white-label architecture?

    The most critical piece of advice I can give is to not try to make a Swiss watch on the very first sprint. One day, you’ll come across a client that will demand all of your features but only in the color pink, and only so that they work on Fridays. It’s better to start with a simpler approach: where you have something in common with the customer and where there are unique demands. Once that’s done, immediately separate the features you’ve identified into their distinct mental corners. This will save you more than once in the future.

    Definitely consider architecture, at least on the fundamental level. No need to build super frameworks, but please do focus on your “best friends”: tokens, components and modularity. Especially when there are twenty brands, and each wants its own shiny “Sell Everything” button.

    Tests are not a luxury, it’s a survival tool. We write automated tests that switch between brands, put in the relevant data, create a user in the needed state, and run scenarios while we sleep. Kind of like a good coffee machine, only instead of coffee we gulp stability.

    And most important of all is communication with the client. Do not try to guess what they want. Instead, offer them a tool so that they can choose themselves. We introduced a visual building block-style tool in the admin panel. If the client wants a black theme with yellow icons, they can help themselves to it.

    To sum up: design a system, but leave room for chaos. If chaos arrives anyway, give it a comfortable place to sit.

    Share. Facebook Twitter Pinterest LinkedIn Tumblr Email
    Lakisha Davis

      Lakisha Davis is a tech enthusiast with a passion for innovation and digital transformation. With her extensive knowledge in software development and a keen interest in emerging tech trends, Lakisha strives to make technology accessible and understandable to everyone.

      Follow Metapress on Google News
      Reconnect with Nature at Northwoods Haven: Your Perfect Getaway in the Heart of the Northwoods
      June 25, 2025
      Secret Winning Tips to Play the Table Games in an Online games
      June 25, 2025
      The Strategic Role of Project Management Scheduling Software in Portfolio-Level Planning
      June 25, 2025
      3W Guide to Truck Bed Mats and Floor Mats: What, Why, and When You Need Them
      June 25, 2025
      The Complete Guide to Dash Cameras and Backup Cameras: Why All Drivers Should Use Them
      June 25, 2025
      Why All Drivers Should Have A Dash Cam: Dash Cameras By Redtiger
      June 25, 2025
      Understanding Rotator Cuff Injuries in Weekend Athletes
      June 25, 2025
      Digital Transformation in Legal Operations: How Cloud-Based Document Management Streamlines Case Preparation
      June 25, 2025
      Corporate Retreats Reimagined: Blending Outdoor Adventure with Strategic Planning
      June 24, 2025
      Switch or Router? What Each One Does and Why It Matters for Your Business
      June 24, 2025
      The Tech Behind the Smart Cooler: Why AI & IoT Are Retail’s Secret Weapon
      June 24, 2025
      How Auto Advertising Companies Measure Your Success?
      June 24, 2025
      Metapress
      • Contact Us
      • About Us
      • Write For Us
      • Guest Post
      • Privacy Policy
      • Terms of Service
      © 2025 Metapress.

      Type above and press Enter to search. Press Esc to cancel.