Software Design

Single Source of Truth: duplicate information always drifts

Some bugs found just before release follow a familiar pattern. The frontend calculates a 10% discount while the backend uses 15%, or a field marked required in the documentation has disappeared from the actual API. Both codebases are fine. The problem is that the same information exists in two places…

5 min read
Cover image for Single Source of Truth: duplicate information always drifts

Some bugs found just before release follow a familiar pattern. The frontend calculates a 10% discount while the backend uses 15%, or a field marked required in the documentation has disappeared from the actual API. Both codebases are fine. The problem is simply that the same information existed in two places and only one side changed.

The principle that prevents these incidents structurally is Single Source of Truth, or SSOT. The name sounds grand, but the idea fits in one sentence. Every piece of information must have exactly one authoritative source.

Key takeaways.

  1. SSOT is the principle that information has one source of truth. It does not mean there must be only one repository
  2. Duplicated information will eventually drift. The real problem is not when it diverges, but when nobody knows which side is correct
  3. When copying is necessary, make it derived. Generate it automatically from the source instead of writing it twice by hand
  4. Caches and replicas do not violate SSOT. What matters is knowing where the source is and which way updates flow

Why does duplication always drift?

The moment information exists in two places, keeping them identical becomes a human responsibility. Tools and compilers do not know about that promise. Every change requires remembering, “Where else did this value exist?” Forget once, and the two values start down different paths.

The worse part comes after the drift. When a constant has different values in two parts of the code, the code alone cannot tell you which is correct. You start digging through git history, tracking down the person responsible, and checking planning documents—a full archaeological excavation. When SSOT collapses, the real cost is not fixing the bug but spending time deciding “which one is the truth.”

Let’s look at a few common cases.

  • Duplicated constants: The 10 MB upload limit is hardcoded separately in frontend validation, backend validation, and the error-message string
  • Duplicated validation logic: The client and server validate email formats with different regular expressions
  • Documentation and code: The API specification and the implementation are maintained separately. Months later, the documentation becomes fiction
  • Database and cache: Cache invalidation is forgotten after the source is updated, so stale data keeps being served
  • Design and code: The color in the design mockup subtly differs from the hardcoded color in the app

The form varies, but the structure is the same: there are two sources of truth, and synchronization depends on people.

Diagram comparing values drifting through manual synchronization without SSOT with values derived from a shared source
The difference between synchronization left to human memory and a structure derived from the source

The principle is not “no copying” but “derivation”

Misunderstanding SSOT leads to reading it as “store information in only one place.” Then caches, read replicas, and build artifacts all look like violations. The actual principle is different. Information may exist in multiple places. The source must be singular, and everything else must be derived from it.

Code generation is a representative way to create derived artifacts.

  • Generate types from the schema: Generating client types and server stubs from an OpenAPI specification makes the specification the source and removes the path for documentation and code to drift
  • Design tokens: Define colors and typography in one token file, then generate them separately for iOS, Android, and web code
  • Shared constants module: Have the frontend and backend import constants from the same package to prevent hardcoded copies at the source
  • Extract documentation from code: Generate API documentation from comments and types so the documentation always follows the code

The common thread is turning the point where a person writes something twice into a point where a machine generates it once. Synchronization responsibility moves from human memory to the build pipeline, and CI knows first when things drift.

Caches and replicas fit the same model. If the source is declared, updates flow only one way—from source to copy—and the period for which a copy may be stale (TTL and invalidation strategy) is defined, SSOT is intact. The violation occurs not when a copy exists, but when people start modifying the copy directly.

The same principle applies to organizations

SSOT is not just about code. Deciding which service owns a piece of data in a microservice architecture, or designating the “official version” among policy documents scattered across an internal wiki, Notion, and Slack, is the same problem.

Documents are especially prone to drifting from code because they have neither compilers nor tests. That is why organizational SSOT starts with agreement, before tools. For example: “This single wiki page is the source for the onboarding process; everywhere else contains only a link.” Replacing copies with links is derivation in the world of documents.

Illustration of a code-generation pipeline that automatically creates types, documentation, and design tokens from a schema source
Turn the point where people write something twice into one where a machine generates it once

Practical checklist

Here are practical criteria you can apply starting tomorrow.

  1. Typing the same value for the second time is a signal: If you are copying constants, validation rules, or configuration values, first consider moving them into a shared module or replacing them with generation
  2. Declare the source: Caches, replicas, and summaries are not inherently a problem. Check that “the source is here” is explicit in code and documentation, and that updates flow one way
  3. Make tools catch drift instead of people: Add schema validation, contract tests, and generated-code diff checks to CI so synchronization failures appear before merge
  4. Beware perfectionism: Overly abstracting everything to eliminate all duplication creates its own cost. Establish SSOT first for information that changes frequently or is expensive when inconsistent

This has the same roots as the DRY (Don’t Repeat Yourself) principle used in refactoring. DRY targets duplication in code logic, while SSOT extends the idea to duplication of data and knowledge. The next time you ask, “This value exists over there too—do I need to update both?” that is exactly where to establish SSOT.