Architecture and migration

Decommissioning starts with the records, not the servers

Settle retention and retrieval requirements before switching anything off. A mechanical export into a simple, access-controlled archive is easier to operate and explain than a clever pipeline.

Read the case: Decommissioning a Telehealth Platform Without Losing the Records

Rehearse regional independence before cutting over

When a region must stand alone, make the dependencies explicit. Copy the shared service, prune what does not belong and re-point consumers through a rehearsed runbook rather than redesigning the service during migration.

Read the case: Carving a Shared Service Out Into a Regional Environment

Draw the data boundary beyond the database

Place state deliberately, then check queues, workflows, analytics, logs and vendors for copies that cross the boundary. Shared compute is an option only where the processing requirements permit it.

Read the case: Data Residency Without a Full In-Country Stack

Payments and commercial rules

Take payment close to the moment you deliver value

Separate the request from fulfilment and treat payment as one eligibility gate. Keeping payment state in your own model makes retries and new product types easier to handle without coupling every workflow to a provider.

Read the case: Take Payment as Close to Shipment as Possible

A price is a catalogue entry; a promotion is a policy

Keep list prices few and stable. Express discounts as named adjustments with explicit conditions and stacking rules, so each marketing idea does not become a data migration.

Read the case: One List Price, Many Coupons: A Pricing Standard for Stripe

Keep the code closest to the money boring

Let the payment-provider component handle payment concepts, not marketing rules. Compose line items in the layer above it so commercial behaviour can change without rewriting the payment core.

Read the case: Make the Invoice Service Dumber

Reliability and data integrity

An existence check is not a uniqueness constraint

A search index, cache or read replica cannot guarantee that another request has not already created the same thing. Define what makes an operation unique, then enforce it with a strongly consistent conditional write.

Read the case: Search-Then-Create Is a Race Condition

Bound the load before adding more capacity

Autoscaling does not supply admission control or stop retry loops. Bound concurrency and fan-out first, then scale on signals that reflect real pressure rather than adding more participants to an overloaded system.

Read the case: Load Testing Told Us Autoscaling Was Unsafe

Test the incident question on a quiet day

Make credential rotation routine, using an inventory and overlapping validity where possible. Then ask what a particular credential touched: if the audit trail cannot answer, improve it before an incident forces the question.

Read the case: Rotating Credentials Without Downtime (and Knowing What They Touched)

AI-assisted engineering

Challenge the tests before implementing against them

Review whether tests can be satisfied by an implementation that misses the intent. Make structural checks enforceable and resolve ambiguity while changing direction still costs a test edit rather than a production revert.

Read the case: Write the Tests Before the Code, Then Review Them Like an Adversary

Delivery and technical judgement

Fix developer experience before changing the runtime

An unreliable local loop or shared development environment is not solved by moving production elsewhere. Fix the seams between repositories and environments first, then make the runtime decision on operational evidence.

Read the case: Fix Developer Experience Before You Re-Platform

Cost the migration, not just the destination

Include engineering effort, hardening, dual running and the product work that will be delayed. A cheaper platform can be the right destination without making migration the right investment now.

Read the case: The Cheaper Platform Isn't the Cheaper Migration

Evaluate the hardest requirement, not the best demo

Prove the security edge, delivery model and regional rollout before committing to a platform. Managed infrastructure can reduce the work without removing your responsibility for data, messaging and an exit path.

Read the case: Evaluating a PaaS That Runs in Your Own AWS Account

Keep the context

The lesson is the short version, not a substitute for the evidence. For the full stories, or to follow how my thinking changes over time, browse all writing.