IBM DevOps and Software Engineering study materials
IBM DevOps and Software Engineering study resources

Strangler Migration with a Shared Oracle Database at Fintrail

IBM DevOps and Software Engineering · Put your knowledge to work in context.

All case studies

Strangler Migration with a Shared Oracle Database at Fintrail

Fintrail has a 1.1M-line .NET monolith on a single Oracle database serving retail banking. Three teams deploy together every two weeks, and any schema change requires a joint release. Leadership wants microservices within 12 months. A pilot extracted "notifications" as a separate service, but it calls back into the monolith's database for customer data, and two other services now read the same ACCOUNT_BALANCE table directly. During the pilot, a dual-write bug produced 340 duplicate emails and showed a stale balance to 1,200 customers. The monolith has no automated regression suite; the only tests are 200 Selenium end-to-end scripts that take 6 hours and fail 20% of the time. There is strong pressure to do a big-bang rewrite because the code is considered legacy. The compliance team requires an auditable history of every balance-changing operation.

1. Which slice should be strangled first, and by what criteria? Defend your choice against the notifications pilot.

Read the worked answer

The notifications pilot failed for a structural reason, not a selection reason: it was extracted without a data boundary, so it became a remote reader of the monolith's schema. That is a distributed monolith, and it will keep coupling releases.

First real slice criteria:

  • Owns its data - the slice can own its tables with no cross-service joins.
  • Bounded coupling - few synchronous calls back into the monolith.
  • Low transactional risk - not the core ledger; a mistake is recoverable.
  • Observable value - independent deployability for at least one team.
  • Testable - a seam exists where behavior can be pinned with characterization tests.

Good candidates: a read-heavy supporting subdomain such as statements/notifications rendering, product catalog, or document generation - with its own schema. Bad first candidates: anything that mutates balances, because compliance requires an auditable history and you cannot afford dual-write ambiguity there.

Before extracting anything, build characterization tests around the chosen seam (API-level, not just Selenium), because the existing 200 end-to-end scripts at 20% flakiness cannot serve as a safety net. Then use the strangler fig pattern: put a facade or routing layer in front, route a small percentage of traffic to the new implementation, and widen behind a flag.

The 12-month goal should be measured in independent deploys and lead time, not in service count. A big-bang rewrite discards years of embedded business rules and replaces a known system with an unproven one under the same deadline pressure.

2. How should data ownership and the dual-write problem be handled, given the 340 duplicate emails and the stale balance?

Read the worked answer

The duplicate emails and stale balances are the expected outcome of writing to two systems without a transaction across them. Dual writes cannot be made safe by ordering the calls differently; a crash or timeout between them always leaves divergence.

Principles:

  1. One writer per table. Assign each table an owning service. No other service reads it directly - including the two reading ACCOUNT_BALANCE. Access goes through the owner's API or through events.
  2. Replace dual writes with a transactional outbox. The monolith writes the business change and an outbox row in the same local transaction; a relay publishes those rows to a broker. The consumer processes idempotently, keyed by a deduplication ID, so redelivery cannot produce duplicate emails.
  3. Change data capture (for example Debezium on Oracle redo) is an alternative where modifying the monolith to write an outbox is slow - but it still requires idempotent consumers and an explicit contract.
  4. Define staleness budgets. If the notifications service can tolerate seconds of lag, asynchronous events are fine. The balance display cannot silently show a stale number; it should read from the owner synchronously or show a clearly labelled cached value.
  5. Reconciliation. During migration, run a periodic job comparing old and new stores, alert on divergence, and keep a rollback path behind a flag.

Compliance: every balance-changing operation needs an auditable history. The event log becomes the audit trail only if it is immutable, ordered per account, and retained under the compliance policy - design that in deliberately rather than bolting it on.

Use expand/contract schema migration so the old and new code can run side by side during cutover without a joint release.

3. How do you avoid rebuilding a distributed monolith, and how should the 12-month plan be sequenced?

Read the worked answer

Distributed monolith warning signs - all present or imminent at Fintrail:

  • services reading another service's tables (already happening with ACCOUNT_BALANCE);
  • synchronous call chains where one request fans through three services;
  • releases that must be coordinated across teams;
  • shared domain libraries or a shared "common" database.

Guardrails:

  • A CI check that fails a build when one service's migrations or queries touch another service's schema. Make the boundary enforceable, not aspirational.
  • Consumer-driven contract tests between services, so integration is verified without end-to-end Selenium.
  • An explicit independent-deployability test: can this service ship alone on a Tuesday without coordinating with the monolith? If not, it is not a service yet.
  • Async events for cross-domain notification, synchronous calls only for genuine queries with a latency budget.

Sequencing over 12 months:

  1. Months 1-3: foundation - pipeline per service, observability, secrets, characterization tests around the first seam, and the schema-ownership guardrail. Retire the Selenium suite progressively in favor of API and contract tests; a 6-hour, 20%-flaky suite cannot gate a migration.
  2. Months 3-6: first two slices extracted with owned data and an outbox; one team deploys independently.
  3. Months 6-9: move the highest-coupling reads off the shared tables; establish the audit event log.
  4. Months 9-12: tackle one balance-adjacent capability only if the earlier steps held, with reconciliation and a rollback plan.

Measure success by lead time, deploy frequency per team, and the number of tables with a single owner - not by service count. A 12-month big-bang rewrite would fail on the same compliance and data-coupling constraints that broke the notifications pilot.