skip to content

Core Design Principles

The language-neutral heuristics every reviewer reaches for: DRY, KISS and YAGNI, separation of concerns, cohesion and coupling, composition, and encapsulation. They are the shared vocabulary for arguing about design without appealing to taste.

part ofSoftware design & architectureoverview, primer and where to startread it →
on this pageshow

explore

questions

73 · 13 sections

What does the DRY principle ("Don't Repeat Yourself") actually require, and why is it stated in terms of knowledge rather than lines of code?

level: juniorimportance: must knowfreq 82%
basics
~20 s

DRY says every piece of knowledge — a rule, a formula, a fact about the system — should live in exactly one place. So when that rule changes, you edit one spot instead of hunting for copies you might miss.

open as a page

How do you tell real (knowledge) duplication from coincidental (incidental) duplication, and what happens when you get that judgement wrong in each direction?

level: middleimportance: must knowfreq 68%
basics
~20 s

Ask whether the copies must always change together for the same reason. If yes, it's real duplication — unify it. If they could evolve separately, it's coincidence — leave them. Merging coincidence creates a shared thing that soon needs flags.

open as a page

Explain the "rule of three" and AHA ("Avoid Hasty Abstractions"), and describe how you decide the moment at which extracting an abstraction pays off.

level: middleimportance: should knowfreq 56%
basics
~20 s

The rule of three says wait until you see the same thing a third time before extracting it — two copies aren't enough to reveal what really varies. AHA adds: prefer some duplication over an abstraction you invented too early.

open as a page

How does applying DRY across service, module, or team boundaries differ from applying it inside a single codebase — and when is deliberate duplication the better architectural choice?

level: seniorimportance: should knowfreq 48%
basics
~20 s

Inside one codebase, sharing costs you a function call. Across services it costs coordination: a shared library of business rules means teams must upgrade and release together. So teams often duplicate small logic on purpose to stay independently deployable.

open as a page

Beyond application code, where else does knowledge get duplicated in a system, and what techniques give you a single authoritative source for it?

level: principalimportance: should knowfreq 38%
basics
~20 s

The same rule often lives in the database schema, the API contract, client code, config files, infrastructure scripts, and the docs. You single-source it by generating the copies from one definition, or by adding automated checks that fail when they disagree.

open as a page

What do the design principles KISS ("Keep It Simple, Stupid") and YAGNI ("You Aren't Gonna Need It") each tell a developer to do, and how do the two differ?

level: juniorimportance: must knowfreq 78%
basics
~20 s

KISS: choose the simplest solution that works — fewer moving parts, easier to read. YAGNI: don't build a feature or extra flexibility until something actually needs it. KISS shapes how you build; YAGNI decides whether to build now.

open as a page

Fred Brooks distinguished "essential" from "accidental" complexity in software. What is the difference, and how does that distinction guide you when someone asks you to "simplify" a codebase?

level: middleimportance: must knowfreq 52%
basics
~20 s

Essential complexity comes from the problem itself — real rules, cases and constraints you cannot delete. Accidental complexity comes from how we built it: tooling, layers, workarounds, duplication. Simplifying means removing accidental complexity; essential complexity can only be moved or made explicit.

open as a page

Martin Fowler frames YAGNI ("You Aren't Gonna Need It") as an economic trade-off between building a presumptive feature now and carrying it. Walk through those costs, and name the situations where applying YAGNI is the wrong call.

level: seniorimportance: must knowfreq 42%
basics
~20 s

Building early costs the build itself plus a delay to real work, and if you guessed wrong you carry and repair dead complexity forever. YAGNI fails where changing later is expensive or impossible: published APIs, stored/wire data formats, security models, and hard non-functional requirements.

open as a page

What is the "speculative generality" code smell, and how do the Rule of Three and Sandi Metz's maxim "duplication is far cheaper than the wrong abstraction" help you decide when to introduce an abstraction?

level: middleimportance: should knowfreq 45%
basics
~20 s

Speculative generality is machinery built for a future that never arrives — an interface with one implementation, unused parameters, hooks nobody calls. Rule of Three: wait for the third occurrence before abstracting. Until then, duplication is safer than guessing the wrong shared shape.

open as a page

How do you build a system that stays cheap to change without violating YAGNI by building speculative extension points? Discuss the mechanisms you would actually use.

level: principalimportance: should knowfreq 30%
basics
~20 s

Buy options, not features: keep code well-factored and tested, defer decisions to the last responsible moment, make data and contracts evolvable (versioned, additive-only, expand/contract migrations), and spend up-front design only on decisions that are hard to reverse.

open as a page

What is Separation of Concerns in software design, and what is a "concern"?

level: juniorimportance: must knowfreq 78%
basics
~20 s

Separation of Concerns means splitting a system so each part deals with one distinct topic — for example, storing data, applying business rules, or drawing the screen — instead of mixing them all in one place.

open as a page

How does Separation of Concerns relate to the Single Responsibility Principle, and where do the two differ?

level: middleimportance: must knowfreq 66%
basics
~20 s

They overlap: SRP says one class should have one reason to change, which is SoC applied to a class. SoC is broader — it applies to functions, files, layers and whole systems, including concerns spread across many classes.

open as a page

What are cross-cutting concerns (logging, authorization, transactions), why are they hard to separate, and what mechanisms exist to handle them?

level: seniorimportance: must knowfreq 62%
basics
~20 s

Cross-cutting concerns are needs like logging, security checks and transactions that apply almost everywhere. Because they touch every operation, they can't simply live in one module; teams pull them out using wrappers, middleware or framework interceptors instead of copying them into every method.

open as a page

Layered architecture is the classic way to separate concerns. What are its rules and its failure modes, and when would you separate by feature slice instead of by technical layer?

level: seniorimportance: should knowfreq 54%
basics
~20 s

Layering splits code into presentation, business logic and data access, with dependencies pointing one way. It fails when every small change touches all layers, when layers just pass data through, or when database concerns leak upward. Splitting by feature keeps related code together instead.

open as a page

When is applying Separation of Concerns harmful? How do you judge that a boundary costs more than it saves?

level: principalimportance: should knowfreq 38%
basics
~20 s

Every boundary adds indirection: more files, interfaces and hops to read. If splitting doesn't let the parts change, deploy or be tested independently — and instead makes one change touch many modules — the split costs more than it saves.

open as a page

In software design, what do the terms "cohesion" and "coupling" mean, and what is the standard rule of thumb about them?

level: juniorimportance: must knowfreq 88%
basics
~10 s

Cohesion is how strongly the things inside one module belong together. Coupling is how much one module depends on another. The rule: aim for high cohesion inside modules and low coupling between them.

open as a page

The classic coupling scale runs from content coupling (worst) to data coupling (best). Walk through the levels and explain why content and common coupling are considered the most dangerous.

level: middleimportance: must knowfreq 58%
basics
~20 s

Worst to best: content (one module touches another's internals), common (shared global data), external (shared external format/device), control (a flag tells the callee what to do), stamp (passing a whole record when only a field is needed), data (passing only the simple values needed). Content and common are worst because a change anywhere breaks everything silently.

open as a page

The classic structured-design cohesion scale ranks a module's internal relatedness from coincidental up to functional. Name the levels in order and give an example of the worst and the best.

level: middleimportance: should knowfreq 52%
basics
~10 s

From worst to best: coincidental, logical, temporal, procedural, communicational, sequential, functional. Coincidental is a Utils class of unrelated helpers. Functional is a module that does exactly one well-defined job, like calculating sales tax.

open as a page

Explain fan-in and fan-out, and the metrics afferent coupling (Ca), efferent coupling (Ce), instability (I = Ce / (Ca + Ce)) and abstractness (A). How do you use them to judge a design?

level: seniorimportance: should knowfreq 38%
basics
~20 s

Fan-in is how many modules depend on this one; fan-out is how many it depends on. Afferent coupling Ca counts incoming dependencies, efferent Ce counts outgoing. Instability I = Ce/(Ca+Ce) runs 0 (very depended-on, hard to change) to 1 (depends on everything, easy to change). Stable modules should be abstract.

open as a page

At architecture scale, how do you decide where module or service boundaries go using cohesion and coupling — and when is accepting tighter coupling the right call?

level: principalimportance: should knowfreq 30%
basics
~20 s

Put boundaries where things change together and are owned by one team; keep what changes together inside one boundary. Accept tighter coupling when the parts share an invariant that must hold immediately, when the domain is still uncertain, or when decoupling would cost more than the change it saves.

open as a page

What does the design guideline "favor composition over inheritance" actually mean, and what is the difference between the two techniques?

level: juniorimportance: must knowfreq 78%
basics
~20 s

Inheritance reuses code by making a new type a subtype of an existing one ("is-a"). Composition reuses code by holding another object as a field and calling it ("has-a"). Prefer composition: it couples types less and can change at runtime.

open as a page

What is the fragile base class problem, and can you walk through a concrete way a harmless-looking change in a base class breaks its subclasses?

level: middleimportance: must knowfreq 62%
basics
~20 s

When a subclass overrides methods, it can depend on how the base class calls its own methods internally. If the base later changes those internal calls — even without changing its public behavior — subclasses silently break. That's the fragile base class problem.

open as a page

When is class inheritance still the right choice over composition? Give concrete criteria, not just "when there's an is-a relationship".

level: seniorimportance: must knowfreq 55%
basics
~20 s

Use inheritance when the subtype is genuinely substitutable for the base everywhere (Liskov), the base was deliberately designed and documented for extension, and both live under one owner. Closed/sealed hierarchies and framework template-method hooks are good fits.

open as a page

A hierarchy has grown to dozens of subclasses because behavior varies along several independent axes (e.g. storage backend × serialization format × compression). How would you restructure it, and what is this failure mode called?

level: middleimportance: should knowfreq 48%
basics
~20 s

It's a combinatorial subclass explosion: with inheritance you need one class per combination (2×3×2 = 12). Replace each axis with a composed collaborator chosen by interface — a Strategy per axis — so you write 2+3+2 = 7 parts and assemble them.

open as a page

Composition usually means delegation. What is delegation in practice, what boilerplate and pitfalls does it bring, and what is the "self-problem"?

level: seniorimportance: should knowfreq 40%
basics
~20 s

Delegation means an object forwards calls to a collaborator it holds. You get flexibility, but must write a forwarder per method, and the wrapped object's internal calls dispatch to itself — so your wrapper can't intercept them. That's the self-problem.

open as a page

What is encapsulation in software design, and why is making every field private while adding a public getter and setter for each one not really encapsulation?

level: juniorimportance: must knowfreq 88%
basics
~20 s

Encapsulation means a component keeps its internal data private and exposes only meaningful operations. A getter and setter for every field still lets outsiders read and change all the state, so nothing is actually hidden and no rules are enforced.

open as a page

David Parnas argued that modules should be decomposed by information hiding rather than by processing steps. What does that mean in practice, and how do you decide what each module hides?

level: middleimportance: must knowfreq 62%
basics
~20 s

Instead of splitting a system into one module per step of the process, split it so each module hides one design decision that is likely to change — a data format, an algorithm, a device, a policy. Everything that would change together lives behind one interface.

open as a page

What is representation exposure, and how does returning an internal mutable collection or storing a caller-supplied object break a class's invariants?

level: middleimportance: must knowfreq 58%
basics
~20 s

Representation exposure is handing out a reference to your internal mutable data. If a method returns the live list, or the constructor stores the caller's list directly, the caller can change that data afterwards without going through your validation, so your rules stop holding.

open as a page

How do you decide which parts of a component belong in its stable public interface and which must stay volatile implementation details? What signals tell you a detail has leaked?

level: seniorimportance: should knowfreq 52%
basics
~20 s

Publish what callers need to express their intent and what you can promise to keep working; hide anything you expect to change — data layout, algorithms, libraries, protocols. A detail has leaked when a change to it forces callers to change too.

open as a page

Encapsulation at the class level is enforced by access modifiers. What enforces it at the module or service level, and why is a shared database between two services the classic failure of encapsulation at that scale?

level: principalimportance: should knowfreq 45%
basics
~20 s

At module or service scale there is no private keyword across process boundaries, so encapsulation must be enforced by explicit published interfaces plus tooling and ownership. A shared database breaks it because every table is effectively a public field any service can read and write.

open as a page

What is the Law of Demeter (also called the "principle of least knowledge") in object-oriented design, and what is a "train wreck" call chain?

level: juniorimportance: must knowfreq 58%
basics
~10 s

A design guideline: an object should only call methods on its immediate collaborators, not reach through them into strangers. A "train wreck" is a chain like order.getCustomer().getAddress().getCity().getName() that navigates someone else's object graph.

open as a page

State the formal Law of Demeter rule: which objects may a method M of an object O legitimately send messages to?

level: middleimportance: must knowfreq 42%
basics
~20 s

Method M of object O may call methods on: O itself, O's own fields/components, M's parameters, objects M creates inside itself, and globals in scope. It may not call methods on objects returned by those calls.

open as a page

Why is "count the dots on the line" a bad test for Law of Demeter violations? Give examples of long chains that are fine and short chains that are not.

level: middleimportance: should knowfreq 38%
basics
~10 s

Dots don't measure coupling. list.filter(...).map(...).count() has many dots but no new dependencies, while a.getB().doIt() has few dots yet reaches into a stranger. What matters is whether you're walking another object's structure.

open as a page

What does strict adherence to the Law of Demeter cost, and how do you decide when the wrapper/delegation overhead isn't worth paying?

level: seniorimportance: should knowfreq 34%
basics
~20 s

Every hidden hop needs a pass-through method, so classes fill with delegating one-liners (the "middle man" smell), APIs get wider, and changes ripple through several files. It's worth paying when the hidden structure is genuinely likely to change.

open as a page

How does the Law of Demeter relate to "Tell, Don't Ask" and to the Feature Envy smell, and how do you refactor a train wreck without simply adding a delegating getter?

level: seniorimportance: should knowfreq 30%
basics
~20 s

A long getter chain usually means the caller is pulling data out to do work that belongs elsewhere (Feature Envy). Instead of adding another getter, move the operation into the object that owns the data — tell it what to do.

open as a page

What does the design principle "Tell, Don't Ask" mean, and what problem is it meant to prevent?

level: juniorimportance: must knowfreq 62%
basics
~20 s

Instead of reading an object's data and deciding what to do outside it, ask the object to do the job and let it decide using its own data. Behavior stays next to the data it needs.

open as a page

How do the "feature envy" code smell and the "anemic domain model" relate to Tell, Don't Ask, and how would you refactor a case of each?

level: middleimportance: must knowfreq 48%
basics
~20 s

Both are what ask-style code looks like at scale. Feature envy is one method using another object's data more than its own; anemic model is data-only classes with all logic in services. Fix by moving the logic onto the class that owns the data.

open as a page

When is querying an object's state ("asking") the right design rather than a violation of Tell, Don't Ask? Give concrete categories.

level: middleimportance: should knowfreq 34%
basics
~20 s

Asking is fine when you only need the value, not a decision about that object: displaying or serializing data, reporting and analytics, test assertions, and pure value objects. The smell is asking and then deciding on the object's behalf.

open as a page

Following Tell, Don't Ask tends to produce objects whose methods return little or nothing. How do you keep such designs testable and observable without re-exposing internal state?

level: seniorimportance: should knowfreq 22%
basics
~10 s

Have the object report outcomes instead of state: return a result type, emit a domain event, or call a collaborator you can substitute in tests. Assert on behavior and outcomes rather than on fields.

open as a page

How does Tell, Don't Ask differ from the Law of Demeter, and why does fixing a "train wreck" like `a.getB().getC().doThing()` by adding delegating methods sometimes make the design worse?

level: seniorimportance: should knowfreq 30%
basics
~20 s

The Law of Demeter limits how far you may navigate - only talk to immediate collaborators. Tell, Don't Ask says who should make a decision. Blindly adding pass-through methods satisfies Demeter's letter while still asking, and bloats the middle object.

open as a page

What is Command-Query Separation (CQS), and how do you classify a method as a command or a query?

level: juniorimportance: must knowfreq 58%
basics
~10 s

CQS says every method should either change state (a command, returning nothing) or return information (a query, changing nothing) — never both. Put differently: asking a question must not change the answer.

open as a page

Name several widely accepted violations of Command-Query Separation in real APIs and explain why each exception is justified.

level: middleimportance: must knowfreq 46%
basics
~10 s

Common accepted mixes: stack pop(), queue poll(), iterator next(), compare-and-swap, atomic getAndIncrement, putIfAbsent, and getOrCreate. Each needs the read and write to happen as one atomic step, which two separate calls cannot guarantee.

open as a page

What is the difference between CQS (Command-Query Separation) and CQRS (Command Query Responsibility Segregation)?

level: seniorimportance: must knowfreq 62%
basics
~20 s

CQS is a method-level style rule: a method either mutates or returns, never both. CQRS is an architecture pattern: separate read and write models — often separate objects, services, or even databases — for the whole system or a bounded context.

open as a page

How does Command-Query Separation relate to referential transparency and pure functions, and what concrete capabilities does that unlock?

level: middleimportance: should knowfreq 34%
basics
~20 s

If queries have no side effects, a call can be replaced by its result without changing the program — that is referential transparency. It lets you cache, reorder, parallelize, retry, and safely inspect calls in logs and debuggers.

open as a page

How would you enforce Command-Query Separation across a large codebase and an HTTP API, and where does the principle break down?

level: principalimportance: should knowfreq 22%
basics
~20 s

Enforce it with conventions the tools can check: naming, return types (commands return nothing or just an outcome), separate command/query interfaces, and lint or architecture tests. On HTTP, map queries to safe methods like GET and commands to POST/PUT/DELETE.

open as a page

In software design, what is the difference between abstraction and indirection, and why is it said that every abstraction introduces indirection but not every indirection is an abstraction?

level: juniorimportance: must knowfreq 55%
basics
~20 s

Abstraction hides detail behind a simpler idea you can reason about, like 'send a payment'. Indirection just means going through something in between instead of calling the thing directly. Abstractions use indirection, but a pass-through wrapper that hides nothing is only indirection.

open as a page

What is a 'leaky abstraction' (Joel Spolsky's Law of Leaky Abstractions), and how should it change the way you design and consume abstractions?

level: middleimportance: must knowfreq 50%
basics
~20 s

A leaky abstraction is one whose hidden details still show through — usually as performance surprises or unusual errors — so you must understand what is underneath to use it correctly. The law says all non-trivial abstractions leak to some degree.

open as a page

'Every problem in computer science can be solved by another level of indirection — except the problem of too many levels of indirection.' What concrete costs does each extra layer impose, and how do you judge whether a new one earns its keep?

level: seniorimportance: must knowfreq 45%
basics
~20 s

Each layer adds code to read, a jump when tracing a bug, another place behaviour can differ, and sometimes runtime cost. A layer earns its place when it hides real complexity or enables a change you actually need now — not a hypothetical one.

open as a page

How do you decide when to extract an abstraction from duplicated code versus leaving the duplication in place, and what is meant by 'a wrong abstraction is more expensive than duplication'?

level: middleimportance: should knowfreq 40%
basics
~20 s

Extract when the pieces are the same idea, not merely the same text, and when they change together for the same reason. If they only look alike, keep the duplication — a shared abstraction forced to serve two different reasons grows flags and branches and becomes harder to remove than the copies were.

open as a page

What makes an abstraction 'deep' rather than 'shallow' in John Ousterhout's sense (interface cost versus functionality hidden), and how would you apply that idea when drawing module or service boundaries?

level: principalimportance: should knowfreq 30%
basics
~20 s

A deep module offers a small, simple interface but hides a lot of work; a shallow one exposes almost as much complexity as it contains. Prefer fewer, deeper boundaries — each interface is a cost paid by every caller.

open as a page

What is the Principle of Least Astonishment (also called Least Surprise) in software design, and how does it drive naming decisions?

level: juniorimportance: must knowfreq 45%
basics
~20 s

It says a component should behave the way a reasonable reader expects from its name and the surrounding conventions. If people are surprised by what a function does, the design is wrong even when the code is correct. Names must promise exactly what happens.

open as a page

Why are hidden side effects considered one of the worst violations of the Principle of Least Astonishment, and how does Command-Query Separation help avoid them?

level: middleimportance: must knowfreq 40%
basics
~20 s

A hidden side effect is a change (write, send, mutate) that the caller cannot see from the call. It breaks the reader's mental model and causes bugs that only appear at runtime. Command-Query Separation says a method either returns data or changes state — never both.

open as a page

What does "predictable error semantics" mean under the Principle of Least Astonishment, and what are the most common ways an API surprises callers when things go wrong?

level: seniorimportance: must knowfreq 35%
basics
~20 s

It means failures are reported the same way everywhere, so callers can predict what happens without reading each implementation: one style of signalling errors, consistent handling of "not found" versus "invalid" versus "broken", and a clearly defined state after a failure.

open as a page

How does the Principle of Least Astonishment apply to default values and default behavior in configuration and API design, and when should a "safe" default win over an "expected" default?

level: middleimportance: should knowfreq 30%
basics
~20 s

Defaults are what most people actually get, so they must match the common case and never hide risk. Pick the value an informed user would have chosen; when the expected default is dangerous — no timeout, verification off — choose the safe one and make the risky option explicit.

open as a page

The Principle of Least Astonishment can conflict with other goals — performance, security, or introducing a genuinely better abstraction. How do you decide when a deliberate surprise is justified, and how do you manage that across a large system?

level: principalimportance: should knowfreq 18%
basics
~20 s

Ask whose expectations you are breaking, how often they will hit it, and how bad it is if they guess wrong. Break an expectation only when the gain is large and durable, then make the surprise loud and impossible to miss — in names, types, and tooling.

open as a page

What does the "fail fast" design principle mean, and why is stopping at the moment invalid state is detected usually better than letting execution continue?

level: juniorimportance: must knowfreq 65%
basics
~20 s

Fail fast means checking for invalid input or state right where it appears and stopping immediately with a clear error, instead of continuing with bad data that causes a confusing failure much later somewhere else.

open as a page

Why is validating invariants inside a constructor or factory (an "always-valid" object) considered a stronger application of fail fast than validating the same rules later, and what practical problems does it introduce?

level: middleimportance: must knowfreq 55%
basics
~20 s

If an object checks its rules when it is created, an invalid one can never exist, so no later code has to re-check or handle it. Validating later means broken objects float around until something notices.

open as a page

When should a system deliberately NOT fail fast, and how do you decide between failing fast and degrading gracefully?

level: seniorimportance: must knowfreq 60%
basics
~20 s

Fail fast when continuing would give wrong answers or corrupt data. Degrade instead when the failure only affects a non-essential part and the core result is still correct - for example hiding a recommendations panel rather than failing the whole page.

open as a page

When applying fail fast, what is the difference between an assertion, a precondition guard, and validation of untrusted external input - and why is it dangerous to enforce a security rule with an assertion?

level: middleimportance: should knowfreq 45%
basics
~20 s

Assertions check assumptions the developer believes are always true and are often switched off in production. Guards check what a caller must supply and always run. Input validation checks data from outside and produces a user-facing error. A security check written as an assertion can vanish in production.

open as a page

Fail fast is about detecting problems as early as possible. Rank the points at which a defect can be caught - compile/build, CI, service startup, first request, and never - and explain what you gain by moving detection earlier.

level: principalimportance: should knowfreq 35%
basics
~20 s

Best is catching it when the code is compiled or built, then in CI, then when the service starts, then on the first request, and worst is never noticing. The earlier the catch, the fewer people are affected and the cheaper the fix.

open as a page

What does the "Single Source of Truth" design principle mean, and what problem does it prevent?

level: juniorimportance: must knowfreq 58%
basics
~20 s

Every fact — a piece of data, a setting, a rule — lives in exactly one authoritative place. Everything else reads from that place or is generated from it, so copies can never quietly disagree.

open as a page

How does Single Source of Truth differ from the DRY (Don't Repeat Yourself) principle, and how does database normalization relate to both?

level: middleimportance: must knowfreq 42%
basics
~20 s

DRY is about not duplicating knowledge in code; SSoT generalises the same idea to data, config, schemas and docs. Database normalization is the data-modelling technique that implements SSoT: each fact stored in exactly one place.

open as a page

If one canonical store holds the truth, how do you keep derived copies — caches, read models, denormalized tables, generated code — from silently diverging from it?

level: seniorimportance: must knowfreq 38%
basics
~20 s

Make every copy generated, never hand-edited; give each one a defined refresh mechanism (regeneration, invalidation, replication, or an event stream); make regeneration cheap and repeatable; and add a check that compares copy against owner and alerts on mismatch.

open as a page

How would you make an API contract or configuration schema the single source of truth across server, clients and documentation, and how do you prove in CI that nothing has drifted from it?

level: middleimportance: should knowfreq 30%
basics
~20 s

Keep one machine-readable schema file as the definition, generate server stubs, client code, validation and docs from it, never hand-edit the generated output, and have CI regenerate and fail the build if the result differs from what is committed.

open as a page

In a system split across several services, how do you decide which service is the single source of truth for a given piece of data, and what goes wrong when two services both write it?

level: seniorimportance: should knowfreq 34%
basics
~20 s

Give each fact to exactly one service — the one that owns the business rules for changing it. Others read it or subscribe to its change events; they never write it. Two writers means conflicting values with no rule for which is correct.

open as a page