See It Flow

Architecture

Data Architecture

Data decisions are often among the most expensive to reverse. Good data architecture makes ownership, system-of-record boundaries, movement, freshness, and lifecycle explicit before accidental coupling hardens.

Mangesh MandlikLast updated:

What Is Data Architecture?

Data architecture defines how data is owned, stored, replicated, secured, retained, and shared across a system. It answers: which domain is the system of record, which storage model fits each access pattern, how operational data differs from analytical data, and how schemas can evolve without breaking consumers.

Clear ownership is a strong default, but it is not the entire discipline. Architects also have to define freshness expectations, lifecycle and deletion rules, replication and movement paths, governance and security controls, and the compatibility plan for schema changes over time.

Ownership
One owner per dataset is a strong default, but some shared reference data still needs explicit stewardship and boundaries.
Storage fit
Choose stores around access patterns: transactional serving, search, caching, streams, or analytical reporting.
Freshness
Every consumer needs a staleness contract. Many caches, replicas, and warehouses are eventually consistent in common configurations; some systems can offer stronger guarantees.

Visual Story

Shared DB → schema coupling → per-service ownership → event replication

Data Architecture

Data Architecture
Monolith DB
0 / 0
👥Up nextTeams Scale

⤢ Expand for synchronized narration timeline

Per-service databases remove schema coupling (Scene 3), but many downstream read models in Scene 4 become eventually consistent. That is one valid pattern, not the only one: APIs, CDC-fed replicas, and analytical pipelines are alternative ways to move data depending on freshness and coupling needs.

Problem It Solves

The cost of unclear data boundaries

When multiple services share a database casually, every schema migration becomes a coordination event. Services cannot evolve independently because the database has become a hidden integration contract.

The deeper problem is unclear system-of-record ownership. If any service can read or write any table, responsibility for correctness, retention, security, and recovery gets blurred. Data architecture solves this by drawing explicit boundaries around who owns a fact, who may copy it, how fresh the copy must be, and how the copy is retired.

It also separates operational workloads from analytical ones. Transaction-serving stores are optimized for correctness and low-latency updates; warehouses and reporting stores are optimized for history, aggregation, and broad scans. Mixing those goals in one place is a common source of pain.

Data Architecture Patterns

How data ownership and movement models work

Data architecture patterns describe how data is owned, moved, and read across services. Read models and event projections are useful, but they are only one option for cross-service data access. Choose the integration model that matches the required freshness, coupling, and operational complexity.

Database per service
A strong default for service autonomy. Cross-service access should usually go through APIs, events, or controlled replicas rather than ad hoc shared-table reads.
Synchronous APIs for owned data
When a consumer needs the owner’s latest state or business decision, calling the owning service directly can be the right choice—at the cost of runtime coupling and dependency availability.
CDC and replicated stores
Change-data-capture streams database changes into other stores without application-level dual-write. Useful for search indexes, cache warming, or downstream materializations.
Read models and analytical pipelines
Consumer-shaped projections and warehouses optimize local queries, reporting, and historical analysis, but they require explicit freshness and backfill semantics.

Data contracts

A data contract is more than a schema file. It captures the structure of the data, what each field actually means, who owns it, how fresh consumers should expect it to be, and how changes remain compatible while producers and consumers roll out at different times. A column named statusis not a contract until its semantics, valid values, nullability, and evolution rules are understood.

Good contracts make schema evolution survivable: additive changes first, deprecations with a migration window, versioning where needed, and clear compatibility expectations for every downstream consumer.

How Architects Think

Why data architecture often outlasts service architecture

Data architecture decisions often outlive service and API decisions because data accumulates history, downstream dependencies, regulatory requirements, and migration cost. That does not mean every data decision is equally irreversible: changing a cache TTL is cheap, while changing a partitioning scheme, retention model, or system of record can be a major program.

Partition keys are not immutable, but they are expensive to change. Online resharding, backfills, dual-write during migration, and reconciliation make change possible—just risky and labor-intensive. The same is true of ownership boundaries: they can evolve, but once many consumers depend on them, the migration becomes an architectural effort, not a quick refactor. That is why data changes connect naturally to Architecture Evolution & Migration.

What would change your decision? If a consumer now needs the owner's freshest state for every transaction, an event-driven projection may stop being the right access pattern. You may switch that path to a synchronous API, a reserved replicated store, or a redesigned ownership boundary instead of pretending all consumers can tolerate the same staleness.

Illustrative Scenario

An e-commerce platform outgrowing a shared database (illustrative scenario)

Context: an e-commerce monolith runs on a single PostgreSQL database. The team is decomposing it into services: orders, inventory, users, and search. Every service currently reads any table it needs directly.

Problem: the inventory team needs to change theproductstable schema. The orders service reads that table too. Coordinating the migration now requires both teams to deploy in lockstep, which destroys independent evolution.

Decision: assign explicit ownership. Inventory owns the product catalogue; orders receives product data via a ProductUpdated event and stores the subset it needs in its own schema. Search consumes the same changes through CDC to update its index. Different consumers get the integration style that matches their workload.

Consequence: orders may read a product name that is briefly out of date. For order confirmation text, that is acceptable: an illustrative freshness SLO could be "99% of ProductUpdated events applied to the orders store within 5 seconds, alert if consumer lag exceeds 30 seconds". Without a stated bound, "briefly" is not testable. If checkout pricing or stock reservation must be exact at decision time, the synchronisation strategy for that path should change—perhaps to a synchronous inventory API or reservation workflow.

Trade-offs

Some data decisions become expensive commitments

Centralised vs distributed ownership

A shared database reduces integration overhead early, but it couples teams at the schema level. Clear service or domain ownership improves autonomy, though some reference or master data still needs deliberate shared stewardship and access rules.

Normalisation vs query performance

Normalised schemas reduce duplication and simplify transactional writes, while denormalised read models, caches, and analytical tables answer specific queries faster. The trade-off is write complexity, freshness management, and storage duplication.

Freshness vs decoupling

Synchronous APIs can return the owner’s latest state but create runtime coupling. Read models, CDC-fed stores, caches, and warehouses usually improve autonomy and query speed, but often with bounded staleness in common deployments.

Polyglot persistence vs operational simplicity

Choosing storage engines by workload can improve fit, but every extra datastore adds backups, security controls, monitoring, migration work, and operational skills to maintain.

What Can Go Wrong

Common data architecture failures

🔗Shared table as integration point

Services read each other’s tables directly. One schema migration breaks downstream consumers with no warning.

👥Unclear ownership

Multiple teams write the same data without one clear system of record. Conflicts and data corruption turn into detective work.

🔥Hot partition key

A shard key is chosen for convenience instead of access distribution. One shard takes most of the traffic, and changing it later becomes a migration project.

📈Warehouse without freshness contract

Analytics users assume the warehouse is real-time, but the pipeline is hours behind and no one documented that staleness.

🧩Schema change without compatibility plan

A producer renames or repurposes a field without a deprecation window. Downstream consumers silently misinterpret the data.

🛡️Sensitive data copied everywhere

PII is replicated into caches, logs, and warehouses without retention or access controls. Deletion and compliance requests become difficult to honor.

When To Use / When Not To Use

✓ Apply stronger data boundaries when
  • → Services or teams need independent deployment and schema evolution
  • → Different domains have different systems of record, retention rules, or access patterns
  • → Operational and analytical workloads should not compete on the same serving store
  • → You need explicit contracts for ownership, freshness, security, and compatibility
⚠️ Keep it simpler when
  • → The system is still a cohesive monolith with one team and no urgent decomposition need
  • → Tight transactional consistency across entities matters more than service autonomy today
  • → The team cannot yet operate streams, CDC, multiple stores, and compatibility governance safely
  • → A local API call solves the freshness problem more simply than building a projection pipeline
Architect's Challenge

You are decomposing a monolith into services. The Orders and Inventory services both need to read the same product catalogue data. What is the correct data architecture decision?

Remember· 30-second mental model

Good data architecture makes ownership, freshness, movement, governance, and evolution explicit before accidental coupling sets the rules for you.

  • 1One owner per dataset is a strong default, but the contract around shared reference data must still be explicit.
  • 2Cross-service reads can use APIs, CDC, read models, replicas, or warehouses; pick based on freshness and coupling needs.
  • 3Many caches, replicas, and analytical stores are eventually consistent in common setups, so document staleness expectations.
  • 4Partition keys and ownership boundaries can be changed, but usually through expensive migrations rather than quick edits.
  • 5Schema types alone are not enough. Data contracts also need semantics, ownership, compatibility, and lifecycle rules.

Key lesson

The riskiest data architecture is the one where nobody can clearly answer who owns a fact, how fresh it is, or how it may change safely.