Case notes

Case note: a new market as configuration, not a project

TL;DRTreat a new market as a configuration set and feature flags over one codebase, not a forked project: catalog, currency, tax, language and promotions become per-market parameters. Marginal markets then launch in weeks, not quarters. The catch is local payments — those are integrations, not configuration, so start them first.

Yes — a new market can be a configuration change rather than a rebuild, and it should be. On a recent engagement we stood up a full route-to-market market — catalog, currency, tax, language, promotions — in roughly six weeks by treating the market as a configuration set and a handful of feature flags over one codebase, not a forked project. One part refused to configure: local payments.

Why does a new market usually turn into a project?

The default failure mode is a fork. A market team wants something slightly different — a tax rule, an extra checkout step, a returnable-deposit scheme — so someone copies the codebase, changes it, and now there are two systems to patch, two on-call surfaces, two sets of regressions to chase. Do that five times and a "platform" is really five platforms wearing one logo. The timeline stretches to quarters because every launch re-derives work that already exists.

It does not have to. A commerce vendor has publicly documented a top-3 global brewer standing up its first market as a Singapore MVP in two months, with later markets running at roughly 35% of the original implementation cost. That is not our project and not our platform, but it is a useful public benchmark: when a market is configuration, the second one is cheap. The number that matters is the marginal cost of market number two, not the heroics of market number one.

What does "a market is configuration" actually mean?

It means the differences between markets live in data and flags, not in branches. On our stack a market is a named configuration set that the same deployed services read at runtime:

Belongs in the configuration setStays in the shared codebase
Catalog, pack hierarchy, available SKUsOrder-capture and stock services
Currency, rounding, price laddersPricing engine (parameterized)
Tax rules and ratesTax engine (parameterized)
Language, labels, legal copyRendering and localization framework
Promotions, loyalty and returnable-deposit rulesPromo, loyalty and returnables engines
Feature flags: which channels and modules are onThe event bus every module publishes to

The engines have to be genuinely parameterized for this to hold. A tax engine that assumes one national rate is a tax engine you will fork the first time you cross a border; standard EU VAT alone spans 17% in Luxembourg to 27% in Hungary across 27 member states as of January 2026, before you reach reduced rates and category rules. A pricing engine that hard-codes a currency is the same trap. Build the engines to take the rules as input, and a new market becomes a new input set — reviewed like code, but not compiled into a fork. It is the same discipline that lets a price-ladder change reach every channel on the same day: the ladder is data, so there is one place to change it.

How do you launch a market as configuration, not a project?

  1. Inventory the real differences first. Sit with the local commercial team and list what actually differs — SKUs, tax, payment rails, promo mechanics, legal text. Most "unique" requirements turn out to be values, not behaviour.
  2. Push every difference into the configuration set. If a requirement cannot be expressed as data or a flag, that is a gap in an engine, not a licence to fork. Fix the engine so the parameter exists, once.
  3. Ship the market dark, flag by flag. Gate each surface behind a feature flag — catalog first, then pricing, then a field-rep flow if the market has reps — so you validate each module without a big-bang cutover.
  4. Reuse the operational surface. One codebase means one deployment and one on-call rota for the whole stack, not a new rota per market. Do not recreate the fork in the org chart.
  5. Treat configuration as reviewed code. Version it, diff it, and put it through the same review and rollout as any code change. A market config nobody can read is a fork with extra steps.
  6. Stand the market up as a test fixture. Load the whole config into a test environment and run order-to-cash and returnables flows against it before anyone logs in.

Returnable-deposit schemes are a classic fork trigger — every market's deposit values and settlement rules differ — so they belong squarely in the configuration set. Kept there, the returnables engine behaves identically everywhere, which is what lets you settle the monthly empties-balance argument with the same reconciliation logic in every country instead of a bespoke spreadsheet per market.

What still refuses to be configuration?

Here is the part that did not go to plan. We had quietly assumed the whole market would configure. It mostly did — and then local payment method integration ate three of the six weeks on its own. Payment rails are not a parameter; each one is an integration with its own sandbox, certification, settlement timing and failure modes. You cannot flag your way into a national wallet.

And the local rails are not optional. A 2021 survey found 66% of Philippine respondents preferred cash on delivery for social commerce, and each Southeast Asian market leans on its own rails — QRIS, PromptPay, DuitNow, VietQR — rather than a single regional card scheme. Configuration decides which payment methods a market shows; it does not build the connections behind them. We should have started the payment integrations on day one, in parallel, instead of after the catalog and tax config felt finished. That is the correction we carried into the next launch: sequence the one genuinely bespoke thing first, and let the configurable ninety percent follow it.

The direction now is to shrink even that bespoke tail: a small library of pre-certified payment connectors a market switches on by flag, so the long pole gets shorter each time we plant it. Get there and the marginal market stops being a project in any sense — it becomes an afternoon of configuration review and a certification wait. That is the version of "new market" worth building toward, and it is why we keep the single-codebase architecture non-negotiable even when a fork looks faster this quarter.

Frequently asked questions

How long does launching a new market actually take with this approach?

On a recent engagement, about six weeks end to end. The configurable parts — catalog, currency, tax, language, promotions — came together quickly. Local payment method integration took roughly half of that because payment rails are bespoke integrations, not configuration. Your timeline hinges mostly on how many local payment connectors a market needs.

Do we need a separate codebase or instance per market?

No. That is the anti-pattern we avoid. Every market runs on the same deployed services, reading a per-market configuration set and feature flags at runtime. Forking per market gives you multiple systems to patch and to put on-call, which is why launches drift into quarters. One codebase, many configurations.

What genuinely cannot be handled as configuration?

Local payment methods. Configuration decides which methods a market displays, but each rail — a national wallet or QR scheme — is its own integration with sandbox, certification and settlement quirks. Start those on day one, in parallel. Most other differences, including tax and returnable-deposit rules, are genuinely just parameters.

Stuck with exactly this?

BrewOS builds the full route-to-market stack for global brewers — order capture, stock, loyalty, returnables, delivery and analytics on one event bus, run by a team of ~20 engineers. Bring us the feature that’s been stuck the longest and we’ll show you how we’d ship it in days.

Book a 30-minute walkthrough