A company operates one platform across many countries with different regulatory regimes, payment rails and tax rules. How should the architecture handle variation without forking per country?
Show the full answer Hide the answer
The two failure modes at the extremes
One rigid system for all countries fails because it cannot express genuine differences — a tax rule, an invoicing format, a required identity check, a mandated payment method — and each accommodation becomes a conditional branch until the code is unreadable.
A fork per country fails differently and worse: every improvement must be made N times, versions diverge, and the organisation loses the ability to ship anything globally. This is the more common failure because it starts as a reasonable expedient for the second country.
The structural answer
Separate the invariant core from the variable periphery, and make the variation data rather than code.
- A common domain model for the concepts that are genuinely universal — an order, a payment, a shipment, a user — with country-specific attributes as extensions rather than as alternative models.
- Country configuration as data: tax rules, required fields, identity verification levels, permitted payment methods, invoice formats, retention periods. A new country should be predominantly a configuration exercise plus a small amount of integration code.
- Pluggable adapters at the genuine variation points — payment rails, tax authorities, logistics providers, identity verification, invoicing — behind stable interfaces. The interface is the design work, and getting it wrong is what forces forks later.
- A rules engine or policy layer for eligibility, pricing and compliance logic that varies by jurisdiction, so the rules are expressible without deploying code.
- Data residency as a deployment concern, with the same software running in a jurisdiction-local installation where required, rather than a different codebase.
What must not be made configurable
Not everything should be a knob. A configuration surface that can express arbitrary behaviour is a programming language with worse tooling, no tests and no review.
Configure the parameters; do not configure the flow. Tax rates, required fields and enabled payment methods are parameters. "In this country the order goes through an extra approval step" is a flow difference, and it belongs in code behind a well-defined extension point — where it can be tested.
The organisational half
- A core platform team owning the invariant model and the extension interfaces, with country teams building within them.
- A defined path for a country team to request a core change, which must be fast — if it is slow, country teams fork, and the fork is permanent. This single process is what determines whether the architecture holds.
- Country launches as a repeatable playbook, with the time-to-launch as the platform's own metric.
- Ownership of shared costs and shared incidents decided in advance, since a defect in the core affects every market simultaneously.
The commercial framing
The value of the shared platform is measured in time-to-launch a new market and in the cost of a feature delivered everywhere. Those two numbers justify the platform investment, and when they degrade, the architecture is drifting toward the fork whether or not anyone has admitted it — which makes them the metrics to watch rather than any structural measure.