InterviewKata
Software architecture · Case study 01 · Governance and decisions

An ADR that avoided a lock-in trap

A US invoicing and payments company is about to launch in India. The platform team proposes the obvious modern answer: replicate the database to a second region with a managed multi-region feature, and get local latency and disaster recovery in one move. Writing the decision down as an ADR, and asking the people it affects before deciding, showed that the proposal would have broken an Indian regulation, rewritten the finance team's reporting, and tied the company's core data to one vendor's API.

Invented companyLedgerly is a realistic composite. The Reserve Bank of India rule and the DynamoDB behaviour it relies on are real and linked under Sources.

1. The situation

Ledgerly sells invoicing and payment collection to small businesses: 1,200 customers in the US, 40 engineers, one PostgreSQL database in us-east-1 holding invoices, payments and customers, about 4 TB. It has signed its first 300 customers in India, where it will collect payments through local payment methods as a licensed payment aggregator. Launch is in five months.

The platform team's RFC: "Move invoices and payments to Amazon DynamoDB global tables with replicas in us-east-1 and ap-south-1 (Mumbai). Indian users get local reads and writes, every region holds a full copy for disaster recovery, and we stop operating a database server."

2. What mattered

Following the advice process (Module 27), the author sent the draft ADR to everyone affected: the payments team, security and compliance, finance, and the data team. Their answers became the decision drivers:

3. The options

OptionHowWhat the review found
A. DynamoDB global tablesOne table, replicas in both regions, writes anywhereEvery replica holds every item, so Indian payment data would also sit in the US: fails the RBI rule. Reporting needs an export pipeline. Writes are billed as replicated write units in each region
B. DynamoDB, one table per regionSeparate tables, no replication; customers routed to their regionMeets residency; same reporting rewrite and data-model redesign, and the vendor's API in the core
C. PostgreSQL regional cellsOne managed PostgreSQL cluster per region; a small global directory maps each customer to its home regionMeets residency; reporting and code unchanged inside a region; two databases to run; a customer can't write in both regions
D. Distributed SQL, rows pinned by regionCockroachDB with regional-by-row tablesMeets residency and keeps SQL; new technology for the team; cost and operations unknown

4. The decision

ADR-047: Regional PostgreSQL cells for customer and payment data

Status: Accepted (supersedes the RFC proposing DynamoDB global tables)
Deciders: Head of platform (decider); consulted payments, compliance, finance, data
Revisit: when a third region is planned, or customers need to write in two regions

Context: India launch in 5 months. RBI (2018) requires payment system data to be
  stored only in India. Indian p99 target 300 ms. 140 SQL reports. RPO 1 min,
  RTO 30 min for payments. Team runs PostgreSQL; no DynamoDB experience.
Decision drivers: residency (must), latency, reporting, recovery, team, lock-in
Options: A global tables, B per-region DynamoDB, C regional PostgreSQL cells,
  D distributed SQL (scorecard linked)
Decision: Each customer has a home region (US or India), recorded in a small
  global directory. All of that customer's data lives only in its home region's
  managed PostgreSQL cluster, with a synchronous standby in a second zone and
  cross-zone backups inside the same country.
Consequences:
  + Residency met by construction; Indian data never leaves India
  + Reporting, queries and team skills carry over; standard SQL, no API lock-in
  - Two production databases; schema changes roll out to both cells
  - Moving a customer between regions is a migration, not a setting
  - Cross-region totals for the board come from an aggregated, non-personal feed
Compliance: fitness function blocks any replication or backup target outside
  the cell's country; quarterly restore test inside India
Dissent: Platform team preferred A for zero database operations; accepted
  risk: the ops load of a second cluster. Option D to be re-evaluated at
  revisit time.

5. How it works

One payment from a customer in Bengaluru, under option A and then under the decision.

6. What decides it

Score the four options with the review's weights, then change the facts. Each toggle is one thing that could have been true about Ledgerly; the winner changes with them, which is why the ADR records its drivers.

Scores from 1 to 5 against residency (weight 5 when the rule applies), Indian latency (3), SQL reporting (3 when it's needed), team familiarity (3), operations (2), lock-in (2), recovery (2), cost (2) and writes from both countries for one customer (8 when needed). Must-haves are knockouts: an option that fails residency, or can't take writes in both countries when that is needed, is out whatever it scores elsewhere. The full scorecard tool is on the Templates page.

7. How it played out

The India cell launched on time. A spike for option A had already shown that the data model needed redesigning around access patterns and that the 140 reports would need a warehouse export: about four months of work the ADR avoided. Nine months later an auditor asked where Indian payment data and its backups are stored; the answer was the ADR and its fitness function, and the audit took a day.

The cost was real too: the team now runs two clusters, and one large customer with offices in both countries had to choose a home region. That trade-off is in the ADR's consequences, so when the customer complained, the discussion started from the recorded reasoning instead of from scratch.

8. Lessons

9. Your turn

  1. Find the hidden replicas (10 min). List every place your system copies customer data: replicas, backups, caches, logs, analytics exports, vendors. Which country is each in?
  2. Draft the ADR (15 min). Use the ADR template for a database choice you face, with drivers, at least three options and the dissent.
  3. Name the revisit trigger (5 min). What fact would make Ledgerly's option D the right answer?
Say it in the interview
  • "We're expanding to another country. Do we replicate the database there?" First, which data may leave which country: residency rules can forbid the very replication that gives you latency. A home region per customer, with each region's data stored only there, meets residency and keeps latency local.

10. Check yourself

Why did DynamoDB global tables fail Ledgerly's residency driver?

Global tables replicate the whole table to every replica region; the RBI rule requires payment data to be stored only in India.

What did Ledgerly give up by choosing regional cells?

Each customer has one home region; that's the price of residency by construction.

What surfaced the residency and reporting problems?

The advice process: compliance and finance knew constraints the platform team didn't.

11. Sources and further reading

SourceWhy
Storage of Payment System Data (Reserve Bank of India, April 2018)The residency rule quoted in section 2.
DynamoDB global tables (AWS documentation)Multi-region, multi-active replication of a whole table.
DynamoDB pricing: global tablesReplicated write units billed in each replica region.
CockroachDB table localitiesRegional-by-row tables, option D.