fedorthinks

Full course · No. 03

A course for the engineer who already writes code but wants to learn how to make architectural decisions, explain them to the team and the business, and see the system whole.

24 modules · 52 concepts · a diagram for each · cheat sheet at the end

Detailed modules
§ 01

An architect differs from a senior engineer not because they know more technologies. They own the consequences of decisions over time.

Course map — 24 modules in six parts

A subway map: first you see all the lines at once, then you ride station by station.

The course goes from mindset to practice. First, how an architect thinks (mindset). Then how a system is built inside (structure) and what changes when it spreads across a network (distribution). After that come the quality properties (quality attributes), working with people (people), and where the profession is heading (future).

Mindset · 1–401 Architect role02 Trade-offs03 Technical debt04 Cognitive loadStructure · 5–905 Decomposition06 Layers & DIP07 API contracts08 Data model09 State & truthDistribution · 10–1210 Distributed systems11 Monolith vs micro12 Sync vs asyncQuality · 13–1713 Performance14 Scalability15 Reliability16 Security17 ObservabilityPeople · 18–2118 Documentation19 Communication20 Leadership21 Business & productFuture · 22–2422 AI-native architect23 Anti-patterns24 Growth
The 24 modules in six parts: mindset → structure → distribution → quality → people → future.

How to read it: every concept gets its English term (the one you'll search docs for and hear in interviews), an everyday image, a diagram, and a card with "what it is / example / cost / related" fields. At the end of the course there's a cheat sheet with every concept on one page.

Long-term thinking — the architect thinks in years

An engineer builds a bridge that a car will drive across tomorrow. The architect asks what happens when trucks start using it, when a new district goes up next door, and when repairs cost more than the bridge itself.

An engineer usually solves the problem as posed. The architect first checks whether the problem was posed correctly. That isn't snobbery or a wish to "talk about the deep stuff." An architectural decision is just usually more expensive to change than a line of code.

The main shift in the head: you stop asking only "how do I do X" and start asking "why do we need X, what are the alternatives, what will we lose, and what will this look like in three years".

Engineerhow to build X?solves the task as posedArchitectwhy X? · alternatives? · what we lose? · in 3 years?nowmonth1 year3 yearsan architectural decision costs more to change than a line of code
The engineer looks at the task as posed. The architect stretches the same question over years.
ConceptLong-term Thinking· thinking in years
What it is

Judging a decision not only by "works tomorrow" but by how it behaves in one to three years.

How it works

Before "how do I build X" — "why X", what the alternatives are, what we lose.

Example

The bridge: will it carry trucks, a new district next door, repairs that cost more than the bridge?

Catch

It's not a licence to build "for growth" — just a question you must ask.

Related
Reversible decisions, trade-offs, technical debt.

Reversible vs irreversible decisions — owning the shape of the system

If a carpenter hangs a shelf wrong, you can move it. If the designer puts a load-bearing wall in the wrong place, the house lives with that mistake for decades.

The architect isn't obliged to personally make every technical decision. But they are obliged to own the decisions that set the shape of the system: service boundaries, the data model, integration protocols, the scaling strategy, security, observability, the migration path.

The useful distinction here is between reversible decisions and irreversible decisions. A reversible decision can be changed in a day or a week: a logging library, a button colour, the internal structure of a small module. An irreversible or expensive-to-reverse decision changes the trajectory of the system: the database, the tenancy model, an API contract, the way events are stored, service boundaries.

Reversible · days or weeksLogging libraryButton colourSmall module internalsdecide fast · fix in a weekIrreversible · yearsDatabaseTenancy modelAPI contractHow events are storedService boundariesthe architect owns these
Make reversible decisions fast. Irreversible ones set the shape of the system — the architect owns them.
ConceptReversible vs Irreversible· two kinds of decisions
What it is

Sorting decisions by the cost of undoing them: days or weeks vs months or years.

How it works

Reversible ones: decide fast, don't argue long. Irreversible ones: slowly, with alternatives and a written record.

Example

A logging library is reversible. The tenancy model or an API contract nearly isn't.

Catch

A week of debate over a reversible detail is as bad as deciding an irreversible one in an hour.

Related
Data model, API contract, service boundaries.
The architect's questions
  • What problem are we actually solving?
  • What changes if load grows 10x?
  • Which decisions here are reversible, and which are nearly not?
  • Who's going to be maintaining this a year from now?

The architect doesn't build "the most correct system" — they build a system that survives reality.

§ 02

There are no free decisions in architecture. Every choice buys one property at the cost of another.

Trade-off — best practice without context is bad advice

An SUV beats a sedan on a muddy road. The sedan beats the SUV in the city. A bicycle beats both if you need to go three blocks and there's nowhere to park.

You can't evaluate an architectural decision outside its context. REST, GraphQL, Kafka, PostgreSQL, Kubernetes, microservices, monolith — all of these are tools with a price. A trade-off is a deliberate exchange: latency vs. throughput, consistency vs. availability, time-to-market vs. maintainability, simplicity vs. flexibility.

The architect doesn't say "Kafka is better than RabbitMQ." They say: "we need per-key event ordering, high throughput, replay, and a durable log; in exchange we pay the operational complexity of Kafka." That's what professional language sounds like.

every choice buys one property at the cost of anotherLatencyThroughputConsistencyAvailabilityTime-to-marketMaintainabilitySimplicityFlexibility
Every decision is a point on several axes at once. Move toward one end and you give something up at the other.
ConceptTrade-offs· a deliberate exchange
What it is

A choice that buys one property at the cost of another — made out loud.

How it works

Name what you gain, what you lose, and why that price is acceptable now.

Example

"Per-key ordering, throughput, replay, a durable log — paid for with Kafka's operational complexity."

Catch
"X is better than Y" without context isn't an argument, it's taste.
Related
CAP / PACELC, over-engineering, sync vs async.

Over-engineering vs under-engineering — complexity is a tax

Every new abstraction is like another room in the house. The room can be useful, but it has to be cleaned, heated, repaired, and explained to guests.

Complexity is useful when it buys an important property: failure isolation, independent release, security, scaling, testability. But complexity "for the future" usually becomes a permanent tax.

The terms over-engineering and under-engineering are only useful together. Over-engineering: complexity showed up before the real pain. Under-engineering: the system has already hit limits, and the architecture left no room to grow. The architect's job isn't to pick an extreme — it's to hold the middle.

Under-engineeringhit limits, no room to growRight-sizedcomplexity buys a propertyOver-engineeringcomplexity before real painlessmore complexitycomplexity pays off only when it buys a property:failure isolation · independent release · security · scaling · testability
Two mistakes at the edges, the right zone in the middle: complexity is justified only when it buys a specific property.
ConceptOver- / Under-engineering· too much vs too little
What it is

Over: complexity before the real pain. Under: the system hit its limits with no path to grow.

How it works
Every new layer or service has to name the property it buys.
Example

Microservices and Kafka at launch for 200 users — over. One table with no indexes when load grows 10x — under.

Catch
Complexity "for the future" doesn't go away — you pay for it every day.
Related
Trade-off, technical debt, cognitive load.
Further reading
  • Architecture: The Hard Parts — Ford, Richards, Sadalage, Dehghani
  • Software Architecture in Practice — Bass, Clements, Kazman
  • Martin Fowler: Is Design Dead?
§ 03

Technical debt isn't always bad. What's bad is debt taken on by accident, not written down, and never meant to be repaid.

Technical debt — a loan, not garbage

A loan on equipment can accelerate a business. A loan for a party just leaves a hangover and interest.

Technical debt is a decision that speeds us up now but creates a future cost of change. Sometimes that's right: you need to test the market, hit a deadline, keep a customer. The problem starts when the team labels everything as debt: bad code, missing tests, chaotic dependencies, outdated libraries.

A useful model is Martin Fowler's Technical Debt Quadrant: deliberate / inadvertent and prudent / reckless. Deliberate-prudent debt: "we're skipping multi-region for now because we have 200 users and one market." Inadvertent-reckless debt: "we didn't know we needed transactions."

RecklessPrudentDeliberateInadvertent“No time for design”corners cut on purpose“Skip multi-region”200 users, one market“What are transactions?”didn't know we needed them“Now we know better”learned while building
Fowler's quadrant: debt can be taken deliberately and prudently (top right). The left-hand cells are the dangerous ones.
ConceptTechnical Debt· borrowing against future change
What it is

A decision that speeds us up now but creates a future cost of change.

How it works

Take it on deliberately, write down what and why, set a trigger for revisiting.

Example

"No multi-region yet: 200 users, one market" — deliberate and prudent.

Catch

If everything is called debt — bad code, no tests, old libraries — the word stops meaning anything.

Related
Debt interest, ADR (recording the decision), trade-off.

Debt interest — debt charges interest

If the road is broken, every trip takes five minutes longer. A month later it's no longer a pothole — it's a tax on the whole city.

The interest on technical debt is the slowdown of every next change. The more often the team touches an area, the more expensive the debt. That's why debt in the hot domain is more dangerous than debt in a rarely-used admin panel.

The architect negotiates a repayment strategy: what exactly counts as debt, what risk it creates, when we revisit the decision, what signal says "time to pay." Without that, "technical debt" becomes an emotional argument, not a managed instrument.

Hot domainAdmin panela changeinterest: the extra time each change costsinterest = slowdown × how often the team touches this code
The same debt: in the hot domain interest is charged on every change, in the admin panel almost never.
ConceptDebt Interest· the running cost of debt
What it is
The slowdown of every next change in code that carries debt.
How it works
Interest ≈ slowdown × how often the team touches that area.
Example

Debt in payments, changed weekly, costs more than debt in an admin panel opened once a quarter.

Catch

Without a repayment strategy, "tech debt" becomes an emotional argument.

Related
Technical debt, cognitive load.
Questions for a debt review
  • Where is it written down why we took this compromise?
  • What interest are we paying each sprint?
  • What would have to happen for this debt to become a blocker?
  • Is there a repayment plan, or at least a trigger for revisiting?
§ 04

A system nobody can hold in their head will break even with strong engineers.

Cognitive load — architecture has to fit in a human head

A subway map is useful not because it shows every bolt in the tunnel. It shows lines, transfers, and direction of travel. That's enough to make a decision.

Cognitive load is the mental effort a system demands from an engineer. There's intrinsic load: the complexity of the domain itself. There's extraneous load: extra complexity from bad architecture, non-obvious links, accidental exceptions, and magic. The architect can't remove business complexity, but they're obliged to reduce accidental complexity.

A good module can be understood on its own. A good bounded context has its own language and its own invariants. A good team owns an area that fits in its head.

what fits in a headMessy systemIntrinsicExtraneousClean systemIntrinsicExtraneousintrinsic = the domain itself (keep) · extraneous = accidental complexity (cut)
Domain complexity (intrinsic) is always there. Architecture decides how much extra (extraneous) gets piled on top — and whether it all fits in a head.
ConceptCognitive Load· mental effort
What it is

How much context an engineer has to hold in their head to change something safely.

How it works

Intrinsic is the domain's own complexity — it stays. Extraneous is accidental — cut it.

Example

A module you can understand on its own vs one where nothing makes sense without the "magic" and exceptions.

Catch
Strong engineers can't save a system that doesn't fit in a head.
Related
Bounded context, Conway's Law, decomposition.

Conway's Law — team structure becomes system structure

If three departments don't talk to each other, their product almost always looks like three products glued together in one menu.

Conway's Law says: an organisation designs systems that mirror the structure of communication inside the organisation. If architectural boundaries don't match team boundaries, the team will keep crossing someone else's turf.

Team Topologies introduces useful labels: stream-aligned team, platform team, enabling team, complicated-subsystem team. That isn't HR fashion — it's an architectural tool. Sometimes the right decomposition of the system starts with the right decomposition of responsibility.

OrganisationSystemTeam ATeam BTeam CPart APart BPart CmirrorsTeam Topologies — four team typesStream-alignedPlatformEnablingComplicated subsystem
Conway's Law: the system mirrors how teams communicate. Team Topologies gives four team types for cutting it on purpose.
ConceptConway's Law· plus Team Topologies
What it is

A system mirrors the communication structure of the organisation that builds it.

How it works

Align team boundaries with system boundaries: each team owns its own area.

Example
Three departments that don't talk ship "three products in one menu".
Catch

If the boundaries don't match, teams keep stepping on each other's turf.

Related

Team Topologies (stream-aligned, platform, enabling, complicated-subsystem), bounded context.

§ 05

A big system becomes manageable only when you can cut it along the right boundaries.

Cohesion & coupling — cut by layers, by domains, or by data flow

A butcher doesn't cut a carcass at random — they cut at the joints. Good decomposition also looks for natural break points.

Decomposition isn't "sort into folders." It's choosing where responsibility ends. High cohesion means everything inside a component is about one thing. Low coupling means the component knows little about other components.

A horizontal cut gives you layers: UI, application, domain, infrastructure. A vertical cut gives you features or bounded contexts: billing, identity, catalog, comments. Real systems need both, but mixing one for the other is dangerous.

BillingIdentityCatalogCommentsUIApplicationDomainInfrastructurehorizontal cut = layers · vertical cut = features / bounded contextshigh cohesion inside a part · low coupling between parts
A horizontal cut gives layers, a vertical one gives features and contexts. A real system is a grid of both.
ConceptCohesion & Coupling· tight inside, loose between
What it is

Everything inside a component is about one thing (cohesion); it knows little about others (coupling).

How it works

Cut horizontally (layers) and vertically (features / contexts) — and don't confuse the two.

Example

A billing module with its own UI → application → domain → infra layers.

Catch
"Sorting into folders" isn't decomposition yet.
Related
Bounded context, layers, modular monolith.

Bounded context — a bad boundary gives itself away through change

If replacing the kitchen tap means tearing the bedroom apart, the problem isn't the tap.

A sign of bad decomposition: a small change ripples across five modules. Another sign: one module changes for different reasons — today because of product, tomorrow because of the database, the day after because of an integration.

The DDD term bounded context is useful precisely here. It's a boundary inside which words have a single meaning. "Customer" in billing and "Customer" in support can be different models. Forcing them into one often creates a brittle "universal" model.

Billing contextSupport contextCustomerCustomerpayer of invoicespayment methodtax detailsperson with ticketscontact channelconversation history≠✗ one shared “universal” Customer → a brittle model
One word, two models: Customer in billing and Customer in support mean different things — and that's fine.
PatternBounded Context· a DDD boundary of meaning
Problem

A small change ripples across five modules; one module changes for different reasons.

Idea
A boundary inside which every word has one meaning and one model.
Example
"Customer" in billing and "Customer" in support are different models.
Cost

Models have to be mapped at the boundaries; translation between contexts.

When to use

When one concept means different things to different parts of the business.

Related
Cohesion / coupling, Conway's Law, microservices.
§ 06

Business logic should depend on business rules, not on the framework, the database, or HTTP.

Dependency Rule and DIP — dependencies flow toward the centre

The foundation shouldn't depend on the colour of the curtains. If it does, the house was designed backwards.

Clean Architecture, Hexagonal Architecture, and Onion Architecture all say the same thing: the important logic belongs at the centre, the details on the outside. HTTP, SQLAlchemy, Next.js, Kafka, Redis, Stripe — these are details. They matter, but they shouldn't define business rules.

The Dependency Inversion Principle says: high-level logic depends on abstractions, and implementations get plugged in from outside. In code that looks like ports and adapters: the service receives a PaymentGatewayProtocol, it doesn't construct a StripeClient inside itself.

Details (outside)Application (use cases)Domainbusiness rulesPaymentGatewayProtocolport · an abstractiondepends onHTTP · Next.jsSQLAlchemyKafka · RedisStripeClientimplements the portevery dependency arrow points inwarddetails plug infrom outside
The domain at the centre depends only on a port. StripeClient, HTTP, and the database are details outside; every arrow points inward.
PrincipleDependency Inversion· DIP, the dependency rule
Problem

Business rules have grown into the framework and the database — you can't test or replace them.

Idea

High-level logic depends on abstractions; implementations plug in from outside.

Example

The service receives a PaymentGatewayProtocol instead of constructing a StripeClient.

Cost
More interfaces and files.
When to use

There are real business rules that must outlive technology changes.

Related
Clean / Hexagonal / Onion Architecture, ports and adapters.

Abstraction — it exists to absorb change, not to look nice

An adapter belongs where the plugs are actually different. If you put an adapter in every socket just because you like adapters, the house gets less safe.

Not every class needs an interface. But anything touching the outside world, time, randomness, the network, the file system, or the database should be replaceable in tests. Otherwise you're not testing business logic — you're booting a small production system inside a unit test.

The price of a layer is more files and more words. The payoff is testability, infrastructure that can be swapped, clean boundaries. If there's no payoff, the layer is dead weight.

Outside world → behind a portTimeRandomnessNetworkFile systemDatabasePortRealproductionFakeunit testsNo interface neededPure functionno outside worldInternal classone implementationno payoff →an extra layer is dead weight
Hide the outside world (time, randomness, network, files, database) behind a port and swap in a fake for tests. Pure logic needs no interface.
PracticeAbstraction· interfaces where change pushes
What it is

An interface goes where the implementation really changes or blocks tests.

How it works

Time, randomness, network, files, database → behind a port; a fake in tests, the real adapter in production.

Example

A business rule is tested without a database, HTTP, or real time — in milliseconds.

Catch
A layer with no payoff is extra files and words, not architecture.
Related
DIP, testability, over-engineering.
§ 07

An API is a promise. Breaking a promise is easy; rebuilding client trust is hard.

API contract — the contract matters more than the transport

Passport control doesn't care about the brand of the door. What matters is which documents are accepted, which rules apply, and what happens when something is wrong.

REST, GraphQL, gRPC, and WebSocket are different ways to talk. REST suits resource-oriented APIs and simple caching. GraphQL helps when different clients need different shapes of read. gRPC is good for typed service-to-service communication. WebSocket is for real-time two-way events.

The transport choice is secondary. The API contract is what matters: schema, errors, idempotency, versioning, backward compatibility, deprecation policy.

RESTresources, cachingGraphQLflexible readsgRPCtyped service-to-serviceWebSocketreal-time, two-waytransportContract — what really mattersSchemaErrorsIdempotencyVersioningBackward compatibilityDeprecation policy
The transport on the left can change. The contract on the right is a promise to clients — and expensive to break.
ConceptAPI Contract· the promise to clients
What it is

A promise: schema, errors, idempotency, versions, compatibility, rules for retiring the old.

How it works

Agree on the contract first, then pick the transport for the job.

Example

REST for resources and caching; GraphQL for varied reads; gRPC for typed service-to-service; WebSocket for real time.

Catch
Breaking a promise is easy; rebuilding client trust is hard.
Related
Idempotency, versioning, reversible vs irreversible.

Idempotency — it saves you from the real world

If you press the elevator button ten times, the elevator shouldn't arrive and leave ten times. It should understand the intent is one.

Idempotency means a repeated operation produces the same final effect. In networked systems, retries are inevitable: timeouts, retries, duplicate webhooks, worker restarts. If creating a payment, order, or message isn't idempotent, the system will eventually do something extra.

The architect designs idempotency at the contract level: idempotency key, unique constraints, safe retries, clear statuses.

the same Idempotency-Key travels with every attemptClient1st trytimeout → retryretryAPIseen this key?1 paymentunique(idempotency_key)same key → same result · the card is charged once
The client sent the request three times with one key — the server recognised the key and created one payment.
ConceptIdempotency· repeat-safe operations
What it is

Repeating an operation gives the same final effect as the first call.

How it works

An idempotency key in the request + a unique constraint in the database + clear statuses.

Example

A payment times out → the client repeats POST /payments with the same key → charged once.

Catch

Without it, repeats (retries, duplicate webhooks, worker restarts) eventually do something extra.

Related
At-least-once delivery, API contract, retries.
§ 08

Code gets rewritten. Data migrates for years. That's why the data model is one of the most expensive architectural decisions.

Data model — data lives longer than applications

You can repaint a facade in a week. A foundation poured wrong reminds you of itself for the lifetime of the building.

The language, the framework, the UI may change several times. But tables, events, keys, relations, and historical records stay. A mistake in the data model often becomes a mistake in every future version of the product.

Normalization reduces duplication and the risk of drift. Denormalization speeds up reads and simplifies the read model. OLTP systems are optimised for transactions, OLAP for analytics. You can't design one model as if it will perfectly serve both classes of work.

App v1App v2 · rewriteApp v3 · rewriteData: tables · events · keys · historyoutlives every rewriteOLTPtransactions · normalizedOLAPanalytics · denormalized reads≠one model can't perfectly serve both kinds of work
The app was rewritten three times; the data stayed. Below: two different kinds of work — transactions (OLTP) and analytics (OLAP).
ConceptData Model· plus OLTP / OLAP
What it is

Tables, events, keys, relations, and history — what survives every rewrite of the code.

How it works

Normalization means fewer duplicates and less drift; denormalization means faster reads.

Example
An OLTP database for orders and a separate OLAP store for reports.
Catch

A mistake in the data model becomes a mistake in every future version of the product.

Related
Irreversible decisions, event sourcing, CQRS.

Event sourcing and CQRS — a strong tool, not a religion

A bank statement doesn't just store the current balance — it stores the history of operations. That's what lets you explain where the balance came from.

Event sourcing stores changes as a sequence of events and reconstructs current state from them. It's useful when history, audit, state recovery, and replay matter. The price is high: event schema evolution, query complexity, eventual consistency, demanding tooling.

CQRS separates the write model from the read model. It can dramatically simplify complex read systems, but it adds synchronisation and lag. Introducing CQRS just because "it sounds architectural" is an expensive way to turn one problem into two.

CommandWrite modelOrderPlacedItemAddedOrderPaidevent log · append-onlyprojectionRead modelshaped for queriesQueryreadsEvent sourcing: state = replay of events · CQRS: separate write and read modelsprice: event schema evolution · lag · harder queries · tooling
A command writes events to the log; a projection builds a read model from them, and queries read that.
PatternEvent Sourcing· state as a log of events
Problem
Current state doesn't explain how we got there.
Idea
Store changes as an event log; state = replaying them.
Example
A bank statement: the balance is the sum of operations.
Cost

Event schema evolution, harder queries, eventual consistency, demanding tooling.

When to use
History, audit, state recovery, and replay matter.
Related
Often paired with CQRS.
PatternCQRS· Command Query Responsibility Segregation
Problem
One model serves both writes and complex reads badly.
Idea
Split the write model from the read model.
Example

Orders are written to a normalized model; the reports screen reads a ready-made view.

Cost
Synchronisation and lag between the models.
When to use

When reads are genuinely complex — not because "it sounds architectural".

Related
Event sourcing, denormalization, eventual consistency.
§ 09

State is complexity that lives somewhere. The more copies of the truth, the more ways to be wrong.

Single source of truth — doesn't mean single database

A company can have many reports, but there has to be one official payroll register. Otherwise payday turns into theatre.

Single source of truth means that for every important fact, you know where the authoritative version lives. A cache, a search index, a read replica, a materialized view — these are derived copies. They can be useful, but they shouldn't pretend to be the primary truth.

Stateful components hold state and demand care: transactions, locking, recovery, backup. Stateless components are easier to scale and replace, but they still depend on state living somewhere else.

App · statelessApp · statelessApp · statelesseasy to scale and replacePrimary DBauthoritative versionCacheSearch indexRead replicaMaterialized viewderived copiesstateful: transactions · locking · recovery · backup
Stateless apps on the left, one authoritative database in the middle, derived copies on the right — which are not the truth.
ConceptSingle Source of Truth· one owner per fact
What it is

For every important fact, it's clear where its authoritative version lives.

How it works

One primary record; the cache, index, replica, and view are derived copies.

Example
Many reports, but one official payroll register.
Catch

It doesn't mean "one database for everything" — it means "one owner per fact".

Related
Stateful / stateless, cache, CQRS.

Cache and locking — a second truth that sometimes lies

The schedule on the fridge is convenient, until someone moves the meeting in the phone calendar.

A cache buys speed at the cost of freshness. The hardest cache question isn't "how to put things in," it's "when to invalidate." TTL, explicit invalidation, write-through, write-behind, cache-aside — these are different compromises between complexity, freshness, and load.

AppCachefast, maybe staleDatabasethe truth1 · read2 · on miss3 · fillTTLExplicit invalidationWrite-throughWrite-behindCache-asideinvalidation strategieshardest part: when to invalidate
Cache-aside: read the cache, on a miss go to the database and put the answer in the cache. On the right: invalidation strategies.

A race condition appears when two operations compete for state. Optimistic locking says: "conflicts are rare, we'll check the version at write time." Pessimistic locking says: "conflicts are dangerous, we'll lock up front." Both are right under different conditions.

Optimistic lockingA reads row (version 1)B reads row (version 1)A writes: v1 → v2 ✓B writes, expects v1 → conflictbet: conflicts are rarePessimistic lockingA takes the lockB waitsA writes, releases the lockB takes the lock, writesbet: conflicts are dangerous
On the left, optimistic locking catches the conflict by version at write time. On the right, pessimistic locking makes the second writer wait.
ConceptCache Invalidation· the cache and keeping it fresh
What it is

A copy of data closer to the reader: speed in exchange for freshness.

How it works

TTL, explicit invalidation, write-through, write-behind, cache-aside — different compromises.

Example
The schedule on the fridge vs the calendar on the phone.
Catch
The main question isn't "how to put it in" but "when to throw it out".
Related
Single source of truth, eventual consistency.
ConceptOptimistic vs Pessimistic Locking· two ways to handle races
What it is

Two ways to stop two operations from corrupting shared state (a race condition).

How it works

Optimistic: check the version at write time. Pessimistic: lock up front.

Example

Two managers edit the same record: the second one gets a conflict and re-reads the data.

Catch

Optimistic struggles with frequent conflicts; pessimistic struggles with heavy lock contention.

Related
Transactions, stateful components.
§ 10

Distribution solves problems of scale, but creates problems of time, order, and trust in the network.

CAP and PACELC — the network is a source of uncertainty

A monolith is a conversation in one room. A distributed system is correspondence between people in different time zones — letters sometimes get lost, arrive twice, or run late.

In a distributed system, you can't just "call a function." Between services there's a network, timeouts, retries, partial failure, different clocks, different versions of code. What was a local transaction in the monolith becomes a coordination protocol.

The CAP theorem is often summarised badly. The practically useful version: during a network partition, you choose between consistency and availability. PACELC adds: even without a partition, you still choose between latency and consistency.

Node ANode B✕network partitionCAP: during a partition, pick oneConsistencyrefuse until in syncorAvailabilityanswer, maybe stalePACELC: else (no partition), still pick oneLatencyorConsistency
The link between nodes is cut — choose consistency or availability. No cut — you still choose: latency or consistency.
ConceptCAP / PACELC· the choices of distributed systems
What it is
During a partition: C or A (CAP). Without one: L or C (PACELC).
How it works
Each store and each scenario states explicitly what it gives up.
Example

A node cut off from its peer: refuse (C) or answer, possibly stale (A).

Catch

"We chose CA" doesn't exist on a network: partitions happen; the only question is what you do then.

Related
Consistency models, trade-off, partial failure.

Consistency models and Saga — consistency comes in flavours

Two people looking at the same Google Doc see the same thing almost instantly. Two people looking at a bank transfer can't settle for "almost."

Strong consistency gives you fresh truth, but costs latency and availability. Eventual consistency tolerates temporary drift, but often scales better. Causal consistency preserves cause-and-effect: if event B depends on A, B shouldn't become visible before A.

Eventualtemporary drift is OKCausalB never shows before AStrongalways fresh truthscales better, tolerates driftfresher truth, costs latency + availabilityshared doc: “almost” is finebank transfer
The consistency scale: from eventual (scales, tolerates drift) to strong (fresh, but more expensive).

The saga pattern breaks a long business transaction into steps with compensating actions. Two-phase commit gives atomicity across resources, but is expensive and fragile in real distributed systems. The architect picks not "the strictest" model but the one sufficient for the risk.

Reserve stockstep 1Charge cardstep 2Ship orderstep 3 fails ✗Release stockundo 1Refund cardundo 2compensating actions undo the steps already done2PC instead: atomic across resources, but costly and fragile
Saga: step 3 failed — compensating actions undo the completed steps 2 and 1 in reverse order.
ConceptConsistency Models· strong · causal · eventual
What it is
How fast, and in what order, everyone sees the same truth.
How it works

Strong: always fresh. Causal: keeps cause-and-effect order. Eventual: catches up later.

Example
A shared doc: "almost instantly" is fine. A bank transfer: it isn't.
Catch

Strong pays in latency and availability; eventual pays in temporary drift.

Related
CAP / PACELC, cache, CQRS.
PatternSaga· a long transaction with compensations
Problem

A business operation spans several services; there's no shared transaction.

Idea
A chain of steps; if one fails, compensating actions undo what was done.
Example

Reserve stock → charge → shipping fails → refund → release the reservation.

Cost
Every step needs a compensation; intermediate states are visible.
When to use

Instead of two-phase commit, which is costly and fragile across a network.

Related
Eventual consistency, idempotency, microservices.
§ 11

Microservices don't fix bad design. They turn local problems into distributed ones.

Modular monolith — an often underrated start

One well-organised warehouse is faster than ten small ones if the same courier is driving between them anyway.

A monolith isn't an insult. A bad monolith is a tangle of dirty dependencies. A good modular monolith has strict internal boundaries, separate domains, explicit interfaces, and a single deployment unit. For a small team, it's often the best starting point.

Microservices help when you need independent releases, autonomous teams, different scaling profiles, failure isolation, or different technology stacks. The price: network calls, observability, distributed transactions, DevOps overhead, versioning, security between services.

Modular monolithBillingmodule · explicit APIIdentitymodule · explicit APICatalogmodule · explicit APIone deploy unit · in-process callsMicroservicesBillingserviceown DBIdentityserviceown DBCatalogserviceown DBnetwork · versioning · ops overhead
On the left, one deploy unit with strong walls inside. On the right, separate services with their own databases and a bill for the network.
PatternModular Monolith· one deploy, strong walls
Problem
The monolith turns into a tangle of dirty dependencies.
Idea

Strict internal boundaries and explicit interfaces — but one deployment unit.

Example

Billing, identity, and catalog modules in one app, talking through module APIs.

Cost
Needs boundary discipline; scales and releases as a whole.
When to use

A small team, an early product. Microservices — when you need independent releases, autonomous teams, different load profiles, failure isolation.

Related
Bounded context, microservices, Strangler Fig.

Distributed monolith and Strangler Fig — the worst of both worlds, and the way out

It's like living in separate apartments but walking next door for every spoon.

A distributed monolith looks like microservices, but the services aren't autonomous: shared database schema, synchronous call chains, releases that only ship together, changes that require touching everyone. The team pays the cost of distribution without getting the independence.

Service AService BService CsyncsyncShared schemaone databasereleases only together · pays for distribution, gets no independence
Distributed monolith: services tied by a synchronous chain and a shared schema — no independence.

The Strangler Fig pattern lets you migrate carefully: wrap the old system, gradually extract capabilities, cut along real business boundaries, not along tables.

ClientFacaderoutes requestsLegacy systemshrinks step by stepBillingCatalogAccountsnew services growcut by business capability, not by tables
Strangler Fig: a facade in front of the old system moves capabilities out to new services one by one, until the old one is gone.
Anti-patternDistributed Monolith· microservices in name only
Signs

Shared database schema, synchronous call chains, releases only together, every change touches everyone.

Why it hurts
You pay for distribution and get no independence.
Example
Separate apartments, but next door for every spoon.
Way out

Own data per service, async links, boundaries by business meaning — or back to a modular monolith.

Related
Modular monolith, bounded context, sync vs async.
PatternStrangler Fig· gradual replacement
Problem
The old system can't be rewritten in one go.
Idea

Wrap it in a facade and gradually move capabilities out into new services.

Example
Extract billing first, then catalog — the facade routes the requests.
Cost
Two systems live side by side for a long time.
When to use
Migrating a live system without a "big rewrite".
Related
Cut along bounded contexts, not along tables.
§ 12

Sync couples systems in time. Async breaks that coupling, but brings delays, duplicates, and ordering complexity.

A phone call requires both sides to be free now. A letter can be read later — but it can get lost, run late, or demand a reply.

A synchronous (sync) call is easy to reason about: send, get an answer. But if the receiver is slow or unavailable, the sender suffers. Async via a queue or pub/sub lets you ride out failures and load spikes, but it demands a different mental model.

A queue usually distributes work across consumers. Pub/sub broadcasts an event to many subscribers. Kafka, RabbitMQ, SQS, Redis Streams — different tools with different ordering, durability, replay, and operational models.

SyncSenderReceiversender waits; receiver down = sender suffersQueueProducerQueueone consumer eachWorker 1Worker 2Pub/subPublisherTopiccopy to everyoneSubscriber 1Subscriber 2Subscriber 3
Sync: the sender waits. Queue: each message goes to one worker. Pub/sub: each event reaches every subscriber.
PatternQueue vs Pub/Sub· work distribution vs broadcast
Problem

A sync call couples systems in time: the receiver goes down, the sender suffers.

Idea

A queue splits work across consumers; pub/sub sends an event to every subscriber.

Example

Kafka, RabbitMQ, SQS, Redis Streams — different ordering, durability, replay.

Cost
Delays, duplicates, ordering complexity.
When to use

The sender doesn't need the result right now; you must ride out failures and spikes.

Related
At-least-once delivery, backpressure, idempotency.

At-least-once delivery — exactly-once is almost always marketing

If a letter is sent twice, decent accounting shouldn't pay the salary twice.

In practice you design for at-least-once delivery plus an idempotent consumer. A message can arrive twice; the handler has to survive it. A dead letter queue is for messages that couldn't be processed after a reasonable number of attempts.

Backpressure is the signal "the receiver can't keep up." Without it, the system gracefully accepts everything and then dies on the inside.

ProducerQueueat-least-oncemay arrive twiceConsumerdedupe by msg idEffectexactly onceafter N retriesDead letter queuebackpressure: “slow down”“exactly-once delivery” is almost always marketing
A message may arrive twice — the consumer drops duplicates by id. After N failures it goes to the DLQ. Backpressure asks the sender to slow down.
ConceptAt-least-once Delivery· plus DLQ and backpressure
What it is
A message is guaranteed to arrive, but maybe more than once.
How it works

An idempotent consumer drops duplicates; a dead letter queue collects messages after N failures; backpressure says "I can't keep up".

Example
A duplicate "pay the salary" message doesn't pay it twice.
Catch

"Exactly-once" is almost always marketing; without backpressure the system accepts everything and dies inside.

Related
Idempotency, queue / pub/sub, reliability.
§ 13

"Make it fast" isn't a requirement. A requirement sounds like latency, throughput, percentiles, and a load profile.

Tail Latency — average response time almost always lies

If nine people got their food in a minute and the tenth waited an hour, the average looks tolerable. The tenth disagrees.

This is the concept of tail latency. First, three words. Latency is the delay of a single operation. Throughput is how many operations the system handles per unit of time. Percentiles show the distribution: p50 is the median, p95 means 95% of requests are faster than that value, p99 is the tail.

The user doesn't feel the average — they feel the tail. Tail latency matters especially in systems where one screen depends on several backend calls: the probability of a slow response stacks up.

requestsp50 · medianp95p99tail latencylatency →one screen = many backend calls → the tail adds up
Most requests are fast, but the tail (p95, p99) is long. The average hides it; the user feels it.
ConceptTail Latency· p95 / p99
Problem

The average response time looks fine while some users wait a very long time.

Idea
Look at percentiles: p50 is the median, p95 and p99 are the tail.
Example

A screen is built from five backend calls: if any one of them lands in the tail, the whole screen is slow.

Cost

You collect a distribution, not one number; you need histograms in your metrics.

When to use
Every time you turn "fast" into a requirement or build an SLO.
Related

The basis for SLOs; grows during a retry storm; visible through observability.

Profiling — profile before you optimise

Fixing performance without a profile is like treating a patient from a photo of their shoes.

This is the practice of profiling: measure first, optimise second. N+1 queries, extra round trips, a bad index, serialisation, lock contention, GC pause, cold cache — they all look like "slow," but they're cured differently.

Amdahl's Law reminds you: speedup is bounded by the part of the system you actually optimise. Little's Law helps you think about queues: more latency at the same throughput means more work-in-progress sitting inside the system.

MeasureProfileFind hotspotN+1 · index · locksFix one thingre-measure · no profile, no optimisationAmdahl’s Lawoptimised partthe rest of the system · sets the limitLittle’s Law: work in progress = throughput × latency
The loop: measure → profile → find the hotspot → fix one thing → measure again. Below, two laws that bound your expectations.
PracticeProfiling· measure before you optimise
Problem

The team "speeds up" the wrong place: a week spent, and the system is no faster.

Idea
A profile shows where the time really goes. Fix only the hotspot.
Example

The "slow page" turns out to be an N+1 query, not a slow language — fixed with one query and a join.

Cost
Time for measuring and tooling; you need a reproducible load profile.
When to use
Before any optimisation. No profile, no optimisation.
Related

Amdahl's Law is the speedup ceiling; Little's Law links latency, throughput, and queues.

§ 14

Scalability is the ability to grow in load and in features without rebuilding the system from scratch.

Vertical vs Horizontal Scaling — they buy different things

You can buy one big truck. You can buy ten small ones. The first is simpler, the second is more flexible — but requires a dispatcher.

Vertical scaling (scale up) means making one machine stronger. Simple, while there's headroom. Horizontal scaling (scale out) means adding more instances. More flexible, but requires a stateless application layer, load balancing, a shared state strategy, and observability.

Databases scale harder than applications. Read replicas help reads, not writes. Sharding splits data but forces you to pick a shard key. A bad shard key turns scaling into a load imbalance.

Vertical · scale upceilingappbigger boxmore CPU / RAMHorizontal · scale outLoad balancerappstatelessappstatelessappstatelessRead replicashelp reads, not writesShardinga bad shard key = load skew
Left: one machine grows until it hits the hardware ceiling. Right: a load balancer and many identical stateless copies. Below: two ways to scale the database.
ConceptVertical vs Horizontal Scaling· scale up / scale out
Problem
Load is growing, and one machine will soon not be enough.
Idea

Vertical: make the machine stronger. Horizontal: put more machines behind a load balancer.

Example

A stateless app is easy to multiply; the database is harder: read replicas for reads, sharding by a shard key for writes.

Cost

Vertical hits a ceiling. Horizontal needs a stateless layer, load balancing, a shared state strategy, and observability.

When to use

Vertical while there's headroom. Horizontal when you need to grow past it.

Related

The X-axis of the Scale Cube; stateless components from the state module; Single Source of Truth.

Scale Cube — scaling features matters as much as scaling load

A city doesn't grow only by population. It grows by schools, hospitals, roads, and rules.

The system has to absorb not just more traffic but more product surface. If every new feature requires rewriting a shared God-service, the system doesn't scale organisationally.

The useful model here is the scaling cube: X-axis is cloning, Y-axis is splitting by function, Z-axis is partitioning by data or tenants.

X-axiscloneappappappY-axissplit by functionbillingcatalogidentityZ-axispartition by datatenants A–Htenants I–Ptenants Q–Z
Three axes of growth: X — copies of one app, Y — different functions in different parts, Z — data or customers split into partitions.
ConceptScale Cube· X / Y / Z axes
Problem

People only think about traffic, but the system breaks from feature growth: everything lives in one God-service.

Idea

Grow along three axes: X — clone, Y — split by function, Z — split by data or tenants.

Example

X: three copies of the app. Y: billing, catalog, identity apart. Z: tenants A–H on one shard, I–P on another.

Cost
Every axis adds boundaries you have to hold and observe.
When to use
When you ask "what breaks first" — and the answer isn't only CPU.
Related

The Y-axis is Bounded Context and microservices; the Z-axis is sharding; mind Conway's Law.

§ 15

A reliable system isn't one where nothing breaks. A reliable system knows what to do when it does.

Retry, Circuit Breaker, Bulkhead — retry without a strategy is an attack on yourself

If a door doesn't open, knocking once is reasonable. Knocking a thousand times a second is now a problem for the door and the neighbours.

Retry is for transient failures. But retries need a limit, a timeout, exponential backoff, and jitter. Otherwise a partial outage turns into a retry storm.

A circuit breaker temporarily stops calls to a stuck dependency. The bulkhead pattern isolates resources: if one downstream dies, it doesn't take all your worker threads and connection pools with it.

retry = limit · timeout · exponential backoff · jittertry 1try 2try 3ok~1s~2s~4s + jitterno limit, no jitter → a retry stormService · bulkheadspool → paymentspool → searchCircuit breakeropen: fail fastPayments APIstuck / timing outSearch API
Top: retries with a growing pause and a random offset. Bottom: separate pools (bulkheads) and a circuit breaker — a stuck Payments API doesn't drag search down with it.
PatternRetry + Circuit Breaker + Bulkhead· resilience to failing dependencies
Problem

A dependency slows down or dies; mindless retries finish it off and eat all of the service's resources.

Idea

Retry with a limit, timeout, backoff, and jitter. Circuit breaker: stop calling the dead. Bulkhead: separate pools so a failure doesn't spread.

Example

The payments API hangs: the breaker opens and fails fast, while the search pool keeps working.

Cost

More settings and states; you have to decide how the system degrades when a dependency is down.

When to use
Any network call to something that can hang.
Related

Retries are only safe with Idempotency; linked to at-least-once and backpressure.

SLI / SLO / SLA — SLOs turn reliability into a contract

"We'll try our best" isn't a train schedule. A schedule says what counts as normal and what counts as a failure.

SLI is what you measure: success rate, latency, freshness. SLO is the target: 99.9% successful requests over 30 days. SLA is a promise to the customer with consequences attached.

The error budget tells you how much unreliability you're allowed to spend. If the budget is burned, the team stops chasing features and fixes reliability. That's the business-language version of engineering quality.

SLI · indicatore.g. success rateSLO · objective99.9% over 30 daysSLA · agreementpromise + penaltyError budget = 100% − SLO = 0.1% ≈ 43 min per 30 daysspent on incidentsleftBudget leftship featuresBudget burnedstop features, fix reliability
SLI is the measurement, SLO the target, SLA the promise to the customer. With a 99.9% SLO the error budget is 0.1% — about 43 minutes per 30 days.
ConceptSLI / SLO / SLA· error budget
Problem

Nobody measured "reliable," so the features-vs-quality argument never ends.

Idea

Measure (SLI), agree on a target (SLO), keep the customer promise separate (SLA). The gap to 100% is the error budget.

Example

SLO: 99.9% successful requests over 30 days. Budget burned — features pause.

Cost

You must honestly pick what to measure and keep the rule when the budget runs out.

When to use

When reliability has to be discussed with the business in one language.

Related

SLIs are often built on Tail Latency; alerts fire on symptoms; it's an NFR in numbers.

§ 16

You can't add security right before release. It has to be built into the access model, the data, the infrastructure, and the processes.

Authentication vs Authorization — different things

A passport proves who you are. A ticket proves where you're allowed to go. One doesn't replace the other.

Authentication (AuthN) answers "who is this?". Authorization (AuthZ) answers "what are they allowed to do?". Confusing them is dangerous: a user can be correctly logged in and still have no right to read someone else's invoice.

RBAC grants permissions through roles. ABAC considers attributes: resource owner, tenant, region, object state. Session-based auth is easier to revoke; JWT is easier to verify without a database, but harder to revoke. The choice depends on threats and lifecycle.

passportticketRequesttoken / sessionAuthenticationwho is this?Authorizationwhat may they do?Resourceinvoice #42Session vs JWTrevoke vs verifyRBAC / ABACroles / attributes403not your invoice
A request passes two different steps: authentication (“who are you?” — the passport) and authorization (“what may you do?” — the ticket). Logged in doesn't mean allowed.
ConceptAuthentication vs Authorization· AuthN / AuthZ
Problem

"The user is logged in" gets confused with "the user is allowed" — and they read someone else's data.

Idea

Two separate steps: AuthN establishes identity, AuthZ checks the right to a specific resource.

Example

A logged-in customer requests another customer's invoice #42 — AuthZ must answer 403.

Cost

Choosing a model: RBAC is simpler, ABAC more precise; sessions are easy to revoke, JWTs easy to verify but hard to revoke.

When to use
In any system where data has an owner.
Related

One layer of defense in depth; the spoofing and elevation-of-privilege threats from STRIDE.

Threat Modeling — professional paranoia

A good architect thinks like an attacker not because they distrust people, but because they trust reality.

Threat modeling is a systematic search for threats before an attack. STRIDE helps you look for them: spoofing, tampering, repudiation, information disclosure, denial of service, elevation of privilege. Defense in depth means several layers of protection: input validation, authz, encryption, audit log, rate limiting, least privilege.

Secrets management isn't "put the key in env and forget." You need to understand rotation, access, audit, blast radius, and what happens during a leak.

STRIDE · find threatsSpoofingfake identityTamperingaltered dataRepudiation“it wasn’t me”Info disclosuredata leakDoSdenial of serviceElevationof privilegeDefense in depthrate limitinginput validationauthzleast privilegeencryptionaudit log
Left: the six STRIDE threat classes to walk every component through. Right: protection in layers — if one layer is breached, the others remain.
PracticeThreat Modeling· STRIDE, defense in depth
Problem

Security gets remembered right before release, when the access model is too late to change.

Idea

Walk the component through STRIDE and put up several layers of protection, not one "main" lock.

Example

A leaked key: what it opens (blast radius), how fast you can rotate it, where it shows up in the audit.

Cost
Time for the review and discipline in secrets management.
When to use
At design time for every new component and integration.
Related

AuthN vs AuthZ is a layer of protection; observability and the audit log let you spot an attack.

§ 17

You can't fix what you can't see. The system has to explain its own state without archaeology in the code.

Observability — monitoring tells you what's wrong, observability helps you understand why

A "check engine" light is useful, but the mechanic still needs gauges, history, and diagnostic tools.

Monitoring answers "something is wrong." Observability answers "why." The three pillars of observability: logs, metrics, traces. Structured logging makes logs queryable. Metrics show aggregates. Distributed tracing follows a request's path through services.

A correlation ID is a small thing that saves nights: one request ID flows through gateway, service, queue, worker, and downstream.

Logsstructured · queryableMetricsaggregatesTracesa request’s pathCorrelation ID: one request id through every hopGatewayreq-7f3aServicereq-7f3aQueuereq-7f3aWorkerreq-7f3aDownstreamreq-7f3amonitoring: something is wrong · observability: why
Three pillars — logs, metrics, traces. One correlation ID passes through every hop, so the whole request path can be put back together.
ConceptObservability· logs · metrics · traces, correlation ID
Problem

Something broke at night, and the cause is hunted by archaeology in the code.

Idea

The system explains its own state: structured logs, aggregate metrics, traces of the request path.

Example

With request id req-7f3a you find the request in the gateway, the queue, and the worker — and see where it got stuck.

Cost
Tooling, data storage, and the discipline to pass the ID everywhere.
When to use
From day one, especially in a distributed system with queues.
Related

The data source for SLIs and Symptom-based Alerting; without it, Profiling is blind.

Symptom-based Alerting — alert on symptoms

The user doesn't care that CPU is at 92%. They care that checkout doesn't work.

A good alert speaks user pain — this is symptom-based alerting: error rate, latency, failed payments, stale data. A bad alert speaks of a cause that can be perfectly normal. If alerts are noisy, the team stops trusting them.

A runbook answers "what to do at 3 a.m." A post-mortem answers "how do we make sure this doesn't happen again." Blameless; the goal is to improve the system, not to find the guilty party.

causessymptomsCPU 92%disk 70%GC pausesoften normal → noisenoisy alerts lose trusterror rate ↑latency ↑failed paymentsstale dataAlertuser painRunbookwhat to do at 3 a.m.Post-mortemblameless · fix the system
Causes like CPU are often normal and make noise. Alerts are built on symptoms of user pain, followed by a runbook and a blameless post-mortem.
PracticeSymptom-based Alerting· runbook, blameless post-mortem
Problem

Alerts fire on causes, the team gets used to the noise and misses a real outage.

Idea
Wake a human only for user pain; every alert gets a runbook.
Example

Not "CPU 92%," but "failed payments went up" — plus a runbook: what to check first.

Cost
You need to know your symptoms and keep runbooks up to date.
When to use
For everything the on-call engineer has to fix at night.
Related

Symptoms are SLIs; the post-mortem is the same written culture as ADRs and RFCs.

§ 18

An unrecorded architectural decision disappears together with the context of its author.

ADR — an Architecture Decision Record beats memory

An oral agreement is good until the first vacation, the first resignation, or the first argument six months later.

An Architecture Decision Record captures context, decision, alternatives, and consequences. An ADR doesn't have to be a novel. A good ADR answers: what problem were we solving, what did we choose, why didn't we choose the alternatives, when do we revisit.

Documentation isn't there for the audit — it's there for the next change. A new engineer has to understand not just "how" but "why."

New engineer6 months laterADR-007 · one decisionContext · what problemDecision · what we choseAlternatives · why not othersConsequences · what it costsRevisit · when to re-checkNext changeknows the why
One ADR, one decision: context, choice, alternatives, consequences, and when to revisit. Six months later a new person learns the “why.”
ToolADR· Architecture Decision Record
Problem

The decision lived in the author's head; the author left, and nobody knows why it was done this way.

Idea

A short record per decision: context, decision, alternatives, consequences.

Example

"We take PostgreSQL, not MongoDB: we need transactions; revisit if document-style workloads appear."

Cost
Half an hour to write. Cheaper than the argument six months later.
When to use
For decisions that are expensive to reverse.
Related

Records Trade-offs and debt; sits next to the RFC; part of Learning in Public.

C4 Model — a diagram is a working tool, not a decoration

A subway map doesn't show the wires or the bolts. It shows lines and transfers. That's enough not to get lost.

The C4 model gives you four levels: Context, Container, Component, Code. The first three are usually enough. A sequence diagram is useful when the order of interactions matters. Full UML is rarely needed; individual diagrams, yes.

Living documentation lives next to the code, updates in the PR, and gets reviewed. A document in a forgotten wiki quickly turns into historical fiction.

zoom in →Contextsystem + peopleContainerapps · DBs · queuesComponentmodules insideCodeclasses · rarelyLiving documentationnext to the code · updated in the PR · reviewedSequence diagramwhen the order mattersForgotten wiki→ historical fiction
The four C4 zoom levels — three are usually enough. Living docs sit next to the code; a forgotten wiki turns into fiction.
ToolC4 Model· living documentation
Problem

Diagrams are drawn for looks: everything on one picture, and a month later it lies.

Idea
Draw by zoom level: Context → Container → Component (→ Code, rarely).
Example

Context: the system, users, external services. Container: web, API, database, queue.

Cost
Diagrams have to be updated in the same PR as the code.
When to use

When the system has to be explained to a new person or another team.

Related

Shows Bounded Contexts and boundaries; a sequence diagram covers the order of calls.

§ 19

The architect talks to engineers, product, business, security, and legal. Each audience hears a different language.

Risk Translation — translate risk into the audience's language

A doctor doesn't only use Latin names with the patient. They explain what will hurt, how long the treatment is, and what to avoid.

This is the practice of risk translation. You can say to an engineer: "we have no idempotency on the payment callback." The business needs to hear: "if the webhook retries, we may charge twice or ship the product twice; that's a financial and reputational risk."

Stakeholder mapping helps you see who cares about what: product wants time-to-market, security wants risk reduction, finance wants predictable cost, support wants understandable behaviour, engineering wants maintainability.

One technical riskno idempotency on the payment callbackTo engineersadd an idempotency keyTo businessmay charge twice → money + trustStakeholder map · who cares about whatProducttime-to-marketSecurityless riskFinancepredictable costSupportclear behaviourEngineeringmaintainability
The same risk sounds different to engineers and to the business. The stakeholder map shows what matters to each.
PracticeRisk Translation· stakeholder mapping
Problem

A technical risk sounds like jargon, and the business doesn't hear it.

Idea

Translate the risk into consequences that matter to this particular audience.

Example

"No idempotency on the callback" → "we may charge twice — a financial and reputational risk."

Cost

You need to know what each stakeholder cares about and speak their language.

When to use
Every time a decision depends on people outside engineering.
Related

The example is Idempotency; the business side is NFRs and cost of delay.

RFC — a written proposal lowers the temperature of an argument

An argument at the whiteboard is often won by the loudest voice. A written proposal forces the arguments to stand apart from the voice.

An RFC (Request for Comments) describes the problem, the constraints, the options, the chosen solution, the risks, and the rollout plan. A good RFC invites criticism before the decision becomes policy.

Disagree and commit works only after an honest discussion. If the team wasn't heard, that isn't commit — that's suppression.

RFC · a written proposalProblemConstraintsOptionsDecisionRisksRolloutDraftarguments on paperReviewcriticism welcomeDecidebefore it’s policyDisagree & commitonly if heardnot heard ≠ commit — it’s suppression
The sections of an RFC and the path of a decision: draft → review with criticism → decide → disagree and commit, but only if everyone was heard.
PracticeRFC· Request for Comments, disagree and commit
Problem
The whiteboard argument is won by the loudest, not the most right.
Idea

In writing: problem, constraints, options, decision, risks, rollout. Criticism comes before the decision.

Example

Before moving to a new queue: an RFC, a week of comments, then a decision and an ADR.

Cost

Slower than "deciding on a call"; needs an owner who drives it to a decision.

When to use

For decisions that touch several teams or are expensive to reverse.

Related

The outcome goes into an ADR; a tool of Influence without Authority.

§ 20

The architect is often still an individual contributor. Their authority comes from clarity of thinking, trust, and the ability to make the team stronger.

Influence without Authority

A conductor doesn't play every instrument, but without one the orchestra quickly becomes a set of talented people playing different pieces.

This is the concept of influence without authority. The architect shouldn't become a bottleneck on every decision. Their job is to set principles, explain boundaries, grow people, and step in where the cost of a mistake is high.

Architect mentoring isn't "do as I do." It's teaching the questions: what alternatives have you seen, what did you give up, how will you test the risk, where does the responsibility end.

BottleneckArchitectteam Ateam Bteam Cevery decision waits in lineMultiplierArchitectprinciplesboundariesquestionsTeams decidegrown by mentoring
Left: the architect as a bottleneck — every decision waits in line. Right: a multiplier — principles, boundaries, and questions, while the teams decide.
ConceptInfluence without Authority· mentoring through questions
Problem

The architect decides everything personally and becomes a queue for every team.

Idea
Influence through principles, boundaries, and questions, not orders.
Example

Instead of "do it this way": "what alternatives did you see, and how will you test the risk?"

Cost
Slower in the moment; it needs trust that takes years to build.
When to use

Whenever you have no direct reports but decisions still need to happen.

Related

Works through RFCs and ADRs; the opposite is the Ivory Tower Architect.

Delegation with Guardrails — delegating doesn't mean transferring ownership

A captain can hand off the wheel, but they can't say the course of the ship is no longer their problem.

Part of architectural decisions should be made by the teams. Otherwise the architect becomes a queue. But there have to be guardrails: principles, review, ADRs, platform constraints, quality gates.

The architect steps in when a decision is irreversible, breaks system invariants, creates security risk, or affects several teams.

Guardrails: principles · review · ADR · gatesTeam decidesmost decisionsplatform constraints · quality gatesarchitect steps in if:irreversiblebreaks invariantssecurity riskmany teams affectedescalate
The team decides on its own inside the guardrails. The architect steps in only on the four signals on the right.
PracticeDelegation with Guardrails· ownership stays
Problem

Either everything goes through the architect (a queue), or nobody owns the course.

Idea

Teams decide on their own inside guardrails; the architect owns the course and steps in on clear signals.

Example

The team picks its logging library itself; changing the tenancy model happens only with the architect.

Cost

Guardrails have to be formulated, written down, and checked automatically where possible.

When to use
When there's more than one team and one architect.
Related

The "irreversible" signal comes from Reversible vs Irreversible; guardrails are ADRs and quality gates.

§ 21

Architecture only makes sense in the context of a business goal. Otherwise it's expensive engineering aesthetics.

Non-functional Requirements — business requirements too

For a shop, "checkout works on Black Friday" isn't a technical detail — it's money.

Non-functional requirements (NFRs) — performance, availability, security, compliance, operability — aren't "technical wants." They're product properties. The architect translates them into business impact: lost revenue, regulatory risk, support cost, speed of market launches.

Cost of delay helps you discuss not just the cost of doing the work, but the cost of waiting. Sometimes an architectural investment without immediate ROI is needed, because without it the next features start getting more expensive.

PerformanceAvailabilitySecurityComplianceOperabilityBusiness impactthe architect translateslost revenueregulatory risksupport costspeed to marketCost of delay: waiting has a price, not only building
Left: non-functional requirements. Right: what they turn into for the business. The architect is the translator in the middle.
ConceptNon-functional Requirements· NFRs, cost of delay
Problem

System quality is treated as a "technical want" and keeps being postponed.

Idea
NFRs are product properties; talk about them in revenue, risk, and cost.
Example
"Checkout survives Black Friday" is money, not a detail.
Cost
You need to estimate the impact in numbers, at least roughly.
When to use
When architectural work competes with features for time.
Related

In numbers: SLOs; postponed work: Technical Debt; the language: Risk Translation.

Build vs Buy — not a matter of pride

Not every company should build its own power station just to turn the lights on.

Building gives you control and differentiation. Buying gives you speed and lowers operational load. Vendor lock-in is a real risk, but on its own it isn't an argument against buying. The question: how expensive is the exit if the vendor changes price, API, or quality?

The architect helps product see the capability map: which capabilities are the core of the business, and which are better bought.

Build · control + differentiationcore domainwhat customers pay you forBuy · speed + less opsauthpaymentsemailmonitoringVendor lock-in → ask about the exit costif the vendor changes price, API or quality — how hard is it to leave?
Build the core customers pay you for; buy the commodity. For anything bought, the key question is the exit cost.
ConceptBuild vs Buy· capability map, vendor lock-in
Problem

People build their own out of pride, or buy everything with no exit plan.

Idea

Build what differentiates the business; buy the commodity. For anything bought, estimate the exit cost.

Example

Your own domain engine — build; email delivery or payments — usually buy.

Cost

Build: time and maintenance forever. Buy: dependence on the vendor's price, API, and quality.

When to use
Before every "let's write our own."
Related

The trap is NIH syndrome; Dependency Inversion helps isolate the vendor.

§ 22

When code is written by agents, the architect's value moves into specification, architectural thinking, and quality control.

Specification-driven Development — spec quality becomes the bottleneck

If the construction crew gets ten times faster, the binding constraint stops being the speed of bricks. It becomes the quality of the blueprints.

AI agents speed up implementation, but they don't remove architecture. A poorly framed task just turns into bad code faster. Specification-driven development means the primary artifact is the specification of behaviour, boundaries, invariants, tests, and acceptance criteria.

In an AI-native process, the architect writes less low-level code and more precise prose. They review the diff, the tests, the architectural boundaries, and the alignment with the spec.

Specbehaviourboundariesinvariantstestsacceptance criteriavague spec → bad code fasterAI agentfast executorCode + teststhe diffArchitect reviewagainst the specfix the spec, not only the code
The spec is the main artifact. The agent quickly turns it into code; the architect checks the code against the spec and, on a miss, fixes the spec.
PracticeSpecification-driven Development· the spec as the main artifact
Problem

An agent writes code ten times faster — and builds the wrong thing just as fast.

Idea

The main artifact is the spec: behaviour, boundaries, invariants, tests, acceptance criteria.

Example

Instead of "build payments": scenarios, errors, the invariant "one payment per order," and tests for it.

Cost
The architect writes more precise prose and less code.
When to use
Whenever an AI agent does the implementation.
Related

Checked by Agent Output Review; invariants come from the API Contract and the Bounded Context.

Agent Output Review — agent code deserves the same discipline as a human PR

A fast junior who writes a thousand lines an hour still needs review. Speed doesn't make code correct.

You can't accept agent code because it compiles. You need tests, evals, import boundaries, type checks, security review. Scenario evaluations matter especially: the system has to pass real cases, not just the happy path.

An AI-native organisation wins not where "everyone is vibe-coding," but where there are strong specifications, small iterations, automated checks, and architectural ownership.

Agent PRcompiles ≠ correctQuality gatestestsscenario evals · not just happy pathimport boundariestype checkssecurity reviewMergeowned
An agent's PR passes the same quality gates as a human's: tests, scenario evals, import boundaries, types, security review.
PracticeAgent Output Review· quality gates for AI code
Problem
Agent code gets accepted because it compiles and looks confident.
Idea
The same automated quality gates and the same review as for a human.
Example

Scenario evals catch that the agent handled only the happy path and forgot the repeated payment.

Cost
The automated checks and import boundaries have to be built in advance.
When to use
Every PR from an agent, no exceptions.
Related

Checks alignment with Specification-driven Development; boundaries come from Dependency Inversion.

§ 23

The architect can be dangerous precisely because they sound convincing. Knowing the traps saves years.

Ivory Tower Architect

Someone draws a perfect city up on the hill but never walks down to see where people actually go.

This is the ivory tower architect anti-pattern: decisions made far from the code, the operations, and the team. The diagrams are beautiful, but the implementation suffers. The cure is simple: read PRs, watch incidents, talk to engineers, walk the change path yourself.

Ivory towerpretty diagramsCureread PRs · watch incidents · talk · walk the pathCode / PRsIncidentsEngineersgapdecisions made far from code, operations and the team
The tower is far from the ground: from the code, incidents, and engineers. The cure is to come down — read PRs, watch incidents, talk, walk the change path.
Anti-patternIvory Tower Architect· architecture from the hill
Symptom
Beautiful diagrams the team can't implement.
Why it hurts
Decisions ignore the real code, operations, and people.
Cure

Read PRs, watch incidents, talk to engineers, walk the change path yourself.

Related

The opposite of Influence without Authority; form over reality is also Cargo Cult.

Resume-driven Development and Cargo Cult

Buying a fire truck because it impresses the neighbours is strange if you don't have water or firefighters.

Resume-driven development picks technologies for a line on the CV. Cargo cult engineering copies the shape of someone else's decision without the reason. NIH syndrome (Not Invented Here) forces you to write your own where a mature external tool would do better.

Another trap is technical perfectionism. The perfect architecture that never reached the user loses to a good-enough system that ships and can evolve.

The real problemstart hereResume-driven devtech for the CVCargo cultcopy the form, not the reasonNIH syndromebuild what you should buyPerfectionismperfect, never shipped
Four traps that pull you away from the real problem: tech for the CV, copying the form, “let's build our own,” and endless polishing.
Anti-patternResume-driven Development· cargo cult, NIH, perfectionism
Symptom

The decision is justified by fashion, someone else's example, or beauty — not by a problem.

Why it hurts

You pay the price of a complex technology without its benefit, or never reach the user.

Example

Kubernetes and microservices for a team of three, "because Netflix does it."

Cure
Start from the problem and honestly name the price of every option.
Related

Cured by Trade-offs and Build vs Buy; often produces a Distributed Monolith.

§ 24

Architecture is an infinite game. Technologies change, but the ability to ask the right questions only gets stronger.

T-shaped / M-shaped Skills — learn from systems, not from hype

A cook grows not from watching knife ads, but from understanding ingredients, heat, time, and taste.

New technologies are worth studying through questions: what problem do they solve, what price do they introduce, where have they already failed, what are the alternatives, what has to be true for them to become useful.

New techthe hypewhat problem does it solve?what price does it add?where has it already failed?what are the alternatives?what must be true to help?Adoptit fitsSkip / waitnot yet
Five filter questions for any new technology. After them, you decide: adopt now or wait.

T-shaped skills give you depth in one area and breadth across the neighbours. M-shaped skills appear in a mature architect: several deep pillars — data, distribution, security, product, AI tools.

T-shapedbreadth: neighbouring areasone deep areaM-shapedbreadthdatadistributionsecurityproductAI toolsa mature architect grows several deep pillars
T: one deep area plus breadth. M: several deep pillars in a mature architect.
ConceptT-shaped / M-shaped Skills· learn from systems, not hype
Problem
People learn every trendy technology, yet gain no depth or judgement.
Idea

Study technologies through questions about problem and price; grow several deep pillars.

Example

A new database: what problem it solves, where it has already failed, what must be true for it to help us.

Cost
Slower than reading announcements; depth takes years.
When to use
With every new technology on the radar.
Related

A guard against Resume-driven Development; the pillars are this course's topics.

Learning in Public — accelerates maturity

When you explain a decision in writing, the gaps in your thinking show up before production finds them.

Learning in public means learning openly, in writing. Write ADRs, RFCs, engineering notes, post-mortems, short breakdowns of decisions. Learn from architects stronger than you — not just what they chose, but how they reasoned.

The architect people imitate usually isn't the one who knows the most terms. It's the person next to whom the team starts asking better questions.

Decideon a real systemWrite it downADR · RFC · notesFeedbackpost-mortems · peersBetter questionsfor you and the teamgaps show up before production
The loop: decide → write it down → get feedback → ask better questions. Gaps in your thinking show up before production.
PracticeLearning in Public· learning in writing
Problem

Production finds the flaws in your reasoning before your colleagues do.

Idea

Write down decisions and breakdowns, share them, learn from the feedback.

Example

ADRs, RFCs, engineering notes, post-mortems, short decision breakdowns.

Cost
Time to write, and the nerve to show unfinished thinking.
When to use
All the time — this is how an architect grows.
Related

Uses ADRs, RFCs, and post-mortems; makes the team stronger, like Influence without Authority.

Final self-check
  • I can name the trade-offs of a decision without ego defence.
  • I understand where the source of truth lives in the system.
  • I tell reversible decisions from irreversible ones.
  • I can explain the architecture to engineering, product, and business in different words.
  • I write decisions so they can still be understood a year from now.
  • I don't hide complexity behind the words "best practice."

The course map: how it all connects

A subway map at the end of the trip: now you see where the lines cross.

Mindset shapes the structure, the data, and the quality. Structure gets recorded in documents, quality gets verified by security and operations, and documents and risks convince the business. Together it all scales into AI-native work and personal growth.

Mindsettrade-offs · debt · cognitive loadStructureboundaries · contractsData & distributiontruth · consistencyQualitylatency · scale · SLOshapesDocs & talkADR · C4 · RFCLead & businessinfluence · NFR · buySecurity & opsauthz · threats · alertsrecorded inverified byconvinceriskAI-native & growthspecs · review · anti-patterns · skillsscales into
The course's eight concept groups and how they connect: from mindset to structure, data, and quality, then on to documents, business, operations, and growth.

Cheat sheet: all 52 concepts of the course

The architect's mindset (1–4)

Long-term Thinkingthinking in years

First check whether the problem is posed right, and how the decision will live in three years.

Reversible vs Irreversibletwo kinds of decisions

Decide fast on what's easy to undo; slowly on what changes the system's trajectory.

Trade-offsa deliberate exchange

Every choice buys one property at the cost of another. Best practice without context is bad advice.

Over- / Under-engineeringcomplexity is a tax

Complexity is justified only when it buys an important property. Hold the middle.

Technical Debta loan, not garbage

A decision that speeds you up now and costs more later.

Debt Interestthe slowdown

The slowdown of every next change. Debt in the hot zone costs the most.

Cognitive Loadfits in a head

How much context you need to change a component safely. Remove accidental complexity.

Conway's Laworg shape = system shape

A system mirrors the communication structure of the organisation.

System structure (5–7, 11)

Cohesion & Couplingone thing inside, little outside

Inside a component — about one thing; outside — know as little about others as possible.

Bounded ContextDDD boundary

A boundary inside which words have a single meaning.

Dependency Inversiondependencies point inward

Business logic depends on abstractions; details plug in from outside (ports and adapters).

Abstractionexists to absorb change

A layer earns its keep by absorbing change and testing without the outside world, not by looking nice.

API Contractcontract over transport

Schema, errors, versioning, and compatibility matter more than REST vs GraphQL vs gRPC.

Idempotencysafe to repeat

Repeating an operation gives the same final effect. Protection from retries and duplicates.

Modular Monolithone deploy, strong walls

One application with strict internal boundaries. Often the best start.

Distributed Monolithworst of both worlds

Services that only ship together. The cost of distribution without the independence.

Strangler Figmigrate piece by piece

Grow the new system around the old one and move traffic over gradually, instead of a big-bang rewrite.

Data and distribution (8–10, 12)

Data Modeldata outlives code

The most expensive decision: normalisation, OLTP vs OLAP.

Event Sourcingthe log of events is the truth

State is rebuilt from events: full history and audit, but expensive to run and evolve.

CQRSseparate write and read models

Commands and queries get their own models; useful when reads and writes differ a lot.

Single Source of Truthone authoritative version

For every fact you know where the primary version lives; the rest are derived copies.

Cache Invalidationa second truth that lies

Speed at the cost of freshness; the hard question is when to invalidate.

Optimistic vs Pessimistic Lockingcheck on write vs lock first

Two ways to stop concurrent edits from overwriting each other.

CAP / PACELCthe network is uncertainty

During a partition: consistency or availability; otherwise: latency or consistency.

Consistency Modelsstrong, eventual, causal

Not the strictest model — the one sufficient for the risk.

Sagaa chain of steps with compensations

A long transaction across services, where each step has an undo instead of a global lock.

Queue vs Pub/Sub

Async decouples in time, but brings delays, duplicates, and ordering.

At-least-once Deliveryexactly-once is marketing

A message can arrive twice; the consumer must be idempotent. DLQ, backpressure.

System quality (13–15)

Tail Latencyp95 / p99

Users feel the tail, not the average.

Profilingmeasure first

Optimise only the hotspot you found; Amdahl and Little set the limits.

Vertical vs Horizontal Scalingscale up / scale out

One big machine, or many identical ones behind a load balancer.

Scale CubeX / Y / Z

Clone, split by function, split by data.

Retry + Circuit Breaker + Bulkheadresilience

Retries with backoff and jitter, a breaker for dead dependencies, isolated pools.

SLI / SLO / SLAerror budget

Measurement, target, and promise; the error budget decides features vs reliability.

Security and operations (16–17)

Authentication vs AuthorizationAuthN / AuthZ

"Who are you?" and "what may you do?" are two different steps.

Threat ModelingSTRIDE, defense in depth

Find threats before the attack and defend in layers.

Observabilitylogs · metrics · traces

The system explains "why"; a correlation ID ties the whole path together.

Symptom-based Alertingrunbook, post-mortem

Alert on user pain; a runbook says what to do; post-mortems are blameless.

Documents and communication (18–19)

ADRArchitecture Decision Record

Context, decision, alternatives, consequences — one per decision.

C4 Modelliving documentation

Diagrams by zoom level that live next to the code.

Risk Translationstakeholder mapping

One risk, different words for engineers and for the business.

RFCdisagree and commit

A written proposal, with criticism before the decision.

Leadership and business (20–21)

Influence without Authoritymentoring

Principles, boundaries, and questions instead of orders.

Delegation with Guardrailsownership stays

Teams decide; the architect steps in on irreversibility, invariants, security, and multi-team impact.

Non-functional RequirementsNFRs, cost of delay

Product properties expressed in revenue, risk, and cost.

Build vs Buycapability map

Build the core, buy the commodity, know the exit cost.

AI-native, traps, and growth (22–24)

Specification-driven Developmentthe spec as artifact

The faster the executor, the more the spec's precision matters.

Agent Output Reviewquality gates

Agent code passes the same checks as a human PR.

Ivory Tower Architectarchitecture from the hill

Decisions made far from the code, operations, and team.

Resume-driven Developmentcargo cult, NIH, perfectionism

Tech for the CV, copying the form, building what you should buy, endless polishing.

T-shaped / M-shaped Skillslearn from systems

Depth plus breadth; a mature architect has several deep pillars.

Learning in Publiclearning in writing

Write decisions down and see the gaps in your thinking before production does.

An architect is an engineer who learned to see the consequences before they became an incident.

End of course · 24 modules · practice starts here.

Re-read this course not as a reference but as a set of questions. Architecture begins where you stop in front of a decision and honestly name the price of every option.