Chaturmind
LearnDSASystem DesignDevOpsEngineering GrowthBlog
Start learning
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML
  • DevOps
  • Engineering Growth

Company

  • Blog
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

Β© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.


← System Design Interview Playbook

Interview Framework

  • The 6-Step Design Framework
  • HLD Fundamentals Refresher
  • Requirement Gathering Practice
  • Domain Decomposition
  • API Contract Design
  • Data Ownership Model
  • Failure Scenario Walkthroughs
  • Architecture Diagramming
  • Back-of-Envelope Estimation

10 Case Studies

  • Design a URL Shortener
  • Design Twitter / X
  • Design WhatsApp
  • Design Netflix
  • Design a Rate Limiter
  • Design a Search Autocomplete
  • Design a Distributed Cache
  • Design a Notification Service
  • Design Uber / Ride Sharing
  • Design a Distributed File Storage System
  • Design a Distributed Task Scheduler
  • Design a Message Queue System
  • Design an Authentication System at Scale
  • Design a Distributed Logging & Metrics Pipeline
  • Design a Food Delivery Platform
  • Design a Real-Time Analytics Dashboard
  • Design a Monitoring & Alerting System
  • Design Container Orchestration Basics
  • Design a CI/CD Pipeline System
  • Design Service Mesh Basics
  • Design a Centralized Configuration & Secrets System
  • Design a Batch Processing System
  • Design a Data Warehouse / Analytics Storage Layer
  • Design Global Content Delivery
  • Case studies

    πŸ—οΈDesign a URL Shortener
  • πŸ—οΈDesign a Rate Limiter
  • πŸ—οΈDesign Twitter / X
  • πŸ—οΈDesign WhatsApp
  • πŸ—οΈDesign Netflix
  • πŸ—οΈDesign a Distributed Cache
  • πŸ—οΈDesign a Notification Service
  • πŸ—οΈDesign a Search Autocomplete System
  • πŸ—οΈDesign Uber / Ride Sharing
  • πŸ—οΈDesign a Web Crawler
  • πŸ—οΈDesign a Payment System
  • πŸ—οΈDesign a Distributed Lock Service
  • πŸ—οΈDesign a Video Streaming Platform
  • πŸ—οΈDesign a Search Engine
  • πŸ—οΈDesign E-Commerce Checkout & Inventory at Scale
Chaturmind
← System Design Interview Playbook

Interview Framework

  • The 6-Step Design Framework
  • HLD Fundamentals Refresher
  • Requirement Gathering Practice
  • Domain Decomposition
  • API Contract Design
  • Data Ownership Model
  • Failure Scenario Walkthroughs
  • Architecture Diagramming
  • Back-of-Envelope Estimation

10 Case Studies

  • Design a URL Shortener
  • Design Twitter / X
  • Design WhatsApp
  • Design Netflix
  • Design a Rate Limiter
  • Design a Search Autocomplete
  • Design a Distributed Cache
  • Design a Notification Service
  • Design Uber / Ride Sharing
  • Design a Distributed File Storage System
  • Design a Distributed Task Scheduler
  • Design a Message Queue System
  • Design an Authentication System at Scale
  • Design a Distributed Logging & Metrics Pipeline
  • Design a Food Delivery Platform
  • Design a Real-Time Analytics Dashboard
  • Design a Monitoring & Alerting System
  • Design Container Orchestration Basics
  • Design a CI/CD Pipeline System
  • Design Service Mesh Basics
  • Design a Centralized Configuration & Secrets System
  • Design a Batch Processing System
  • Design a Data Warehouse / Analytics Storage Layer
  • Design Global Content Delivery
  • Case studies

    πŸ—οΈDesign a URL Shortener
  • πŸ—οΈDesign a Rate Limiter
  • πŸ—οΈDesign Twitter / X
  • πŸ—οΈDesign WhatsApp
  • πŸ—οΈDesign Netflix
  • πŸ—οΈDesign a Distributed Cache
  • πŸ—οΈDesign a Notification Service
  • πŸ—οΈDesign a Search Autocomplete System
  • πŸ—οΈDesign Uber / Ride Sharing
  • πŸ—οΈDesign a Web Crawler
  • πŸ—οΈDesign a Payment System
  • πŸ—οΈDesign a Distributed Lock Service
  • πŸ—οΈDesign a Video Streaming Platform
  • πŸ—οΈDesign a Search Engine
  • πŸ—οΈDesign E-Commerce Checkout & Inventory at Scale
HomeLearnSystem DesignSystem Design Interview PlaybookInterview Framework
βœ“ FreeAdvancedΒ· 8 min read

Data Ownership Model

Database-per-service as the default, why a shared database between services is a design smell, and the real patterns (API composition, event-driven sync, saga) for querying and writing across ownership boundaries.

Published September 23, 2026


Data Ownership Model

Domain Decomposition draws the service boundaries; this is the follow-up an interviewer almost always asks next: who owns which data, and what happens when two services both need it?

Database-per-service as the default

Order Service   β†’ owns β†’ orders_db   (only Order Service ever writes here)
Inventory Svc   β†’ owns β†’ inventory_db (only Inventory Service ever writes here)

Each service should own its own data store exclusively β€” no other service writes to it directly, ever. This is what makes independent deployability real: if two services shared a database, a schema migration for one could break the other, and neither could evolve its data model independently. A shared database between services is one of the clearest signals a proposed decomposition (Domain Decomposition) hasn't actually separated the services β€” it's separated the code while leaving the data coupled.

The problem this creates: cross-service queries

Once data is genuinely partitioned per service, a natural question a candidate needs to answer is: how does the Order page show the customer's name AND their order history AND the item's current stock level, if that data lives in three different services' databases? Three real patterns answer this:

1. API composition

API Gateway / BFF β†’ calls Order Service, Customer Service, Inventory Service in parallel
                  β†’ composes the three responses into one view for the client

The simplest pattern: a composing layer (an API gateway, or a backend-for-frontend) calls each owning service and assembles the result. Works well when the composition is read-only and the services can tolerate the composing layer's added latency (calling 3 services and waiting for all 3, ideally in parallel not sequentially).

2. Event-driven data synchronization

Inventory Service β†’ publishes "StockLevelChanged" event β†’ Order Service subscribes,
  keeps its OWN local cached copy of stock level (denormalized, eventually consistent)

When composition-time calls are too slow or too tightly coupling, a service can instead subscribe to events from the owning service and maintain its own local, denormalized, eventually-consistent copy of the data it needs. This trades strong consistency (the copy can be briefly stale) for speed and decoupling (no synchronous call needed at read time) β€” the same consistency/latency tradeoff that underlies most of distributed systems design.

3. Saga pattern for cross-service writes

Place Order saga:
  1. Order Service: create order (PENDING)
  2. Inventory Service: reserve stock β€” if fails, Order Service: cancel order (compensating action)
  3. Payment Service: charge β€” if fails, Inventory Service: release stock (compensating action),
     Order Service: cancel order (compensating action)
  4. Order Service: mark order CONFIRMED

When a single business operation needs to write across multiple services' data (place an order = reserve inventory + charge payment + create order record), there's no single database transaction spanning all three β€” a saga coordinates the sequence of local transactions, with an explicit compensating action defined for each step to undo it if a later step fails. This is the standard answer to "how do you keep data consistent across service boundaries without a distributed transaction," and it trades ACID atomicity for eventual consistency plus explicit rollback logic the team has to write and maintain.

Follow-up questions this topic invites β€” and their answers

Q: Why not just use a distributed transaction (two-phase commit) instead of a saga? A: Two-phase commit requires all participants to be available and locks resources across all of them until every participant commits β€” this creates tight coupling and availability coupling exactly opposite to why services were split apart in the first place; it doesn't scale well across independently-deployed, independently-available services, which is why sagas (accepting eventual consistency) are the standard practical answer instead.

Q: What happens if a compensating action itself fails? A: This is a genuinely hard, real problem β€” compensating actions need to be designed to be retriable (idempotent) and, in production systems, failures here often require manual intervention or a dead-letter queue with alerting, since an unrecoverable partial saga state is a real operational risk that needs to be surfaced, not silently swallowed.

Q: Does API composition always mean calling all services synchronously and waiting? A: Not necessarily β€” calls to independent services can be made in parallel (not sequentially) to reduce total latency, and a composing layer can also apply timeouts/fallbacks per service (see Timeout Strategy, Circuit Breaker Pattern) so one slow dependency doesn't block the entire composed response.

Q: How do you decide between event-driven sync and API composition for a specific cross-service read? A: If the data is read far more often than it changes and slight staleness is acceptable, event-driven local caching avoids repeated cross-service calls entirely; if the data changes frequently or staleness is unacceptable for that specific read, real-time API composition is the more correct (if slower) choice β€” the decision hinges on the read/write ratio and the actual staleness tolerance of that specific use case.

Previous

API Contract Design

Next

Failure Scenario Walkthroughs

AI Tutor

Lesson: Data Ownership Model

Quick actions

AI responses can be inaccurate. Verify critical information.