Hello! I’m Karthi, an Android engineer on the Cross Border (XB) Client Core team responsible for building foundational code for Mercari’s global apps.This article is part of the series discussing how we developed a new global service and covers android engineering strategy for global app development.
Building a product for a worldwide audience takes careful planning, especially when we can leverage a proven foundation. Our goal for the Global app is ambitious: deliver a unified, high‑performance experience at global scale. This post pulls back the curtain on the key decisions behind our approach, including the context and trade‑offs that shaped our roadmap.

The Technology Cornerstone: Why We Chose Native
The choice of tech stack had to reflect not only theoretical advantages, but also our ability to build on existing knowledge and infrastructure. We chose native development based on first‑hand experience operating multiple stacks across different Mercari apps:
- Mercari Japan Marketplace: Jetpack Compose first, MVVM
- Mercari US: React Native
- Mercari Hallo: Flutter
For the new app, we prioritized three criteria:
- Faster time to market
- A small, focused team
- A scalable foundation for long‑term growth
On paper, hybrid technologies like Flutter or React Native can seem like the obvious fit for faster development. In practice, the right choice depends on the organization’s existing capabilities and assets.
Mercari has experience across building both hybrid and native apps. Our largest product is the Japan Marketplace app (10M+ downloads), a Compose‑first app fully rewritten about three years ago. Its architecture has proven itself at scale, and we’ve since built a rich set of reusable libraries for authentication, client event logging, experimentation, and more, along with a robust CI/CD system.
By reusing this foundation—platform libraries, infrastructure, and a large native knowledge base—we can move faster while keeping a scalable, shared platform across apps.
On high level our native tech stack looks like below

Tradeoff: Avoiding past complexity
While cross‑platform tools offer advantages, our experience building Mercari Hallo with Flutter highlighted a major drawback for us: our existing foundations weren’t reusable. We would have needed to recreate core libraries and tooling from scratch, slowing delivery and increasing risk. To maintain speed and stability, native was the clear strategic choice for us.
Streamlining Development: Embracing the Monorepo
If reuse is a cornerstone, structure matters. We considered two obvious approaches:
- A monorepo hosting apps and libraries
- Multiple repositories separating apps and libraries
Each has pros and cons. A monorepo centralises code, improves consistency, and simplifies maintenance. Multiple repositories keep code isolated and can reduce dependency complexity.
We chose Monorepo, reinforced with clear boundaries and strict dependency rules, to capture monorepo’s benefits while limiting sprawl. On the top level our Monorepo structure has 2 major sub directories : product, library
Product: Contains independent directories for products like jp and global. Each product has its own app , core and feature directories and its modules.
Library: Contains all foundation modules used across products.

To ensure the structure remains clean and dependencies don’t cross boundaries, we enforce strict separation rules using the modules-graph-assert plugin. This plugin validates our dependency graph during CI and fails the build if any violations are detected. To find violations, we have two major rules for dependency isolation. 1) Product modules must remain isolated from each other (Ex: product/global/abc → product/jp/xyz is not allowed), and 2) library modules are foundational and cannot depend on product modules (Ex: library/logger → product/global/abc is not allowed).
Tradeoff: scalability hurdles
Monorepos can face scalability issues as they grow, increasing clone and build times. Today, the centralisation and code sharing outweigh those costs for us, and we retain the option to split when it becomes beneficial by maintaining clear internal boundaries .
Deploying Worldwide: One Global Build
For our release strategy across countries, we chose a "one global build" approach. This means that Mercari ships a single Android application binary (APK/AAB) that serves all regions. The other option is to create separate builds for each market, like a TW version, HK version, etc.
The decision to go with "one global build" was based on several key factors. A single global build simplifies the release pipeline by having only one build to test, validate, and deploy, which means faster releases and less operational overhead. It also makes maintenance easier since bug fixes and features go to all users simultaneously—eliminating the need to manage multiple versions or coordinate staggered rollouts across different country-specific builds. Additionally, a single codebase reduces code divergence by preventing country-specific builds from drifting apart over time, which can create technical debt and inconsistencies.
This brings us to the important question of how country-specific customization will be handled and executed smoothly if we use one build. We achieve this through our BFF (Backend for Frontend) layer and Remote Configuration systems. BFF can serve different content, features, or business logic based on the user’s country selection via our powerful remote configuration mechanism, which manages country-specific feature flags and configuration.
Tradeoff: Single point of failure
By going with this approach, we need to consider the risk of a critical bug or issue in the build, as it affects all users across all regions simultaneously. By creating a solid foundation and enforcing discipline to have configurable functionalities as shared above, we are confident that we can avoid such risks.
Backend Integration: Performance via BFF and gRPC
Backend integration choices—protocols and architecture—form an important part of tech stack decisions and shape app development’s flexibility and performance. Here we made a decision to deviate from Mercari’s Japan app REST-based approach.
Architecture: A BFF layer is introduced for the global product to optimize the clients with focused APIs. Beyond typical BFF benefits like efficient data fetching and ability to generalize business logic in this layer, it gives us flexibility to deliver country-specific experiences, complementing the one-build approach.
Protocol: gRPC is being chosen as the protocol for the global app backend for its performance characteristics and for its type-safe contracts, which streamline the client and backend communication without adding any custom validation. Additionally, it provides options like richer communication patterns, including streaming over HTTP/2. For gRPC on Android, we chose Wire (from Square) due to its similarities with Retrofit and its fit with our OkHttp-based stack.
Tradeoff: Tooling and maintenance
Adopting gRPC adds complexity: we now maintain two client stacks because shared services still use REST. We also need a proto delivery mechanism, and debug tooling for gRPC can be less mature for developers and QA compared to JSON/HTTP. We accept this in exchange for performance and other long term gains.
Conclusion
By leaning on a proven native foundation, structuring development in a disciplined monorepo, and making pragmatic choices in areas like Backend integration and release strategy, we’re building for speed, stability, and scale. These foundations are the structural steel of a skyscraper—strong, deliberate, and ready to bear the weight of a global launch.
Hope this offers a good peek into our Android development. Please check out our other posts to learn more about the systems powering our global project.

