Most systems that fail under load do not fail because the code is slow. They fail because a boundary is in the wrong place, and every request pays for it.
That distinction decides how the work goes. Profiling finds hot code. It cannot find a missing seam — and when latency is structural, no amount of tuning recovers it. A pricing engine we took apart had a twelve-second median that had been optimised at for years; the fix was decomposition, and it returned a six-fold improvement in weeks.
What gets designed
Boundaries, first. Where must state be consistent, and where is eventual consistency not merely acceptable but correct? Everything else follows from that answer, and getting it wrong is the expensive mistake — it is cheap to move a function and very costly to move a boundary once teams have formed around it.
Delivery guarantees, explicitly. “We use Kafka” is not a guarantee. A transactional outbox plus idempotent consumers keyed on a deterministic identifier is a guarantee. On a settlements platform, that difference is the gap between a reconciliation team and no reconciliation team.
Failure modes, deliberately. Which components may degrade, which must not, and what each one does when its dependency stops answering. Systems do not degrade gracefully by accident.
How the work is done
With your engineers, in the open. Every consequential decision is written into an ADR carrying the alternatives and the reason for the choice, because the value of a decision in two years is entirely in whether the reasoning survived.
A migration is sequenced so each step is independently valuable and independently reversible. Strangler-fig, live traffic behind the existing interface, no cutover weekend. If a step cannot be rolled back, it gets split until it can be.