A Roadmap for Sharding and Distributed Transaction Design to Break Through DB Performance Limits During Traffic Surges
When you operate a service with a large user base, you eventually hit a wall called “performance.” As traffic grows, transaction throughput (TPS) spikes, and you reach the CPU, I/O, and connection-pool limits of a single database. Vertical scaling (Scale Up) has clear limits, and at that point you must prepare for a major architectural leap: horizontal scaling (Scale Out).
This article goes beyond listing sharding techniques. From the perspective of system architects and backend developers, it provides an in-depth distributed-system architecture design roadmap that stably handles large-scale traffic while also guaranteeing data consistency.
1. Why a Single Database Is Not Enough (The Fundamental Limits of Scalability)
A database is inherently a powerful system that guarantees ACID (Atomicity, Consistency, Isolation, Durability). However, that same strong-consistency mechanism can itself become a bottleneck. Because every request must go through a single resource pool (the DB instance), once traffic exceeds a certain point even a high-performance instance has a clear upper bound on throughput.
The first and most important step to overcome this limit is sharding.
2. The First Step in Database Scaling: Understanding Sharding and Implementation Strategies
Sharding splits a huge dataset into multiple smaller database pieces (shards) and stores them in a distributed fashion. It is like splitting one giant library into several specialized branches (shards).
The Art of Sharding Key Design: Between Even Distribution and Transaction Grouping
The success or failure of sharding depends more than 90% on sharding key design. The sharding key is the criterion that determines which shard data is assigned to.
⚠️ Fatal pitfall: the hot-spot problem The most common issue is a hot spot. For example, in an e-commerce site, if lookup/purchase requests for a particular popular product ID (e.g., 1001) surge, data with that ID concentrates on a specific shard. Even though the overall system is distributed, only that shard becomes overloaded, creating a “distributed single point of failure” that can bring down the entire service.
💡 Solutions:
- Key distribution: When using time-based data (e.g., daily logs), include a time range in the key so that shards are rotated periodically.
- Combined hashing: Use pure hash-based sharding, but introduce a mechanism that periodically rebalances shard groups (re-sharding) to reduce dependence on any particular key.
Comparison of Major Sharding Implementation Patterns
| Pattern | Principle | Advantages | Disadvantages and Considerations |
|---|---|---|---|
| Range-based | Split by key range (e.g., A–M on Shard 1, N–Z on Shard 2) | Favorable for range-based queries (e.g., “query last month’s data”) | Hot spots easily form at range boundaries |
| Hash-based | Feed the key into a hash function to determine the shard index | Very even data distribution | Range queries are impossible or complex |
| Directory-based | A separate metadata store (directory) manages key-to-shard mapping | Highest flexibility; redistribution is easy | The directory server itself can become a bottleneck |
In practice, combining these three—using Directory-based as the metadata management layer and Hash-based for actual data assignment—is the most stable hybrid approach.
3. The Hardest Problem: Distributed Transaction Processing Strategies
Even after distributing data via sharding, problems arise when a single business flow (e.g., inventory deduction → payment record → point accrual when creating an order) must span multiple shards. This is where distributed transactions are needed.
ACID vs. BASE: Redefining the Transaction Model
Traditional RDBMSs guarantee ACID, and 2PC (Two-Phase Commit) is what enforces this in a distributed environment. 2PC requires every participating node to succeed in the “Prepare” phase before it can “Commit.”
However, 2PC causes high overhead and reduced availability under network latency or participant-node failure. In large-scale distributed systems, a shift to the BASE (Basically Available, Soft state, Eventually consistent) model—which prioritizes availability and partition tolerance over consistency—is inevitable.
A Modern Alternative: The Saga Pattern and Event-Driven Architecture (EDA)
The Saga pattern is the most representative way to sidestep the complexity of distributed transactions. It moves away from the obsession that “everything must match perfectly” and adopts “making it consistent eventually (Eventual Consistency).”
If a failure occurs on the “inventory deduction” shard during order processing, instead of rolling everything back as in 2PC, Saga executes a compensating transaction. In other words, it performs a “cancel” action on already successful steps (e.g., the payment record) to return the system to a logically consistent state.
The following table shows the key differences between the two approaches.
| Characteristic | 2PC (Two-Phase Commit) | Saga Pattern (Eventual Consistency) |
|---|---|---|
| Consistency model | Strong consistency | Eventual consistency |
| Failure handling | Atomic rollback | Compensating transaction |
| Overhead | High (increased network round trips) | Low (asynchronous message-based) |
| Suitable environment | Core financial logic where transaction failure is catastrophic | Commerce with complex business flows such as orders/inventory/notifications |
4. Adding Layers for Completeness: Technologies That Support Sharding and Distributed Transactions
Sharding and Saga alone are not enough. Supporting layers are needed to back these two core strategies.
Applying the CQRS Pattern: Separating Reads and Writes
Command Query Responsibility Segregation (CQRS) separates the data model into a “write (Command)” path and a “read (Query)” path.
- Write (Command): Records data to the sharded DB via transactions (Saga). (Write Model)
- Read (Query): Uses a separate data store optimized for read-only access (e.g., Elasticsearch, Redis cache). (Read Model) Thanks to this structure, surging read requests can be handled by the cache or search engine without loading the DB, dramatically reducing database load.
Caching Layer and Polyglot Persistence
An in-memory cache such as Redis should be the first place to absorb load. Also, not all data needs to go into a relational DB. Using a Polyglot Persistence strategy—storing user session data in Redis, search data in Elasticsearch, and complex relationships in a Graph DB—is essential so that each domain uses an optimized database.
💡 Practitioner’s empirical advice: Looking at large commerce service cases, we initially tried to solve everything with MySQL sharding. However, because the transaction boundaries between Payment and Inventory were so distinct, we realized that rather than attempting sharding first, separating microservices by domain and having each service take responsibility for its own sharding and Saga maximizes architectural stability.
5. Conclusion: A Scaling Architecture Design Checklist for Your Service
Large-scale distributed system design is not completed in one go. Use the following checklist to inspect your current service’s bottlenecks and the technology stack you need.
✅ Scaling architecture inspection checklist
- Traffic analysis: What are currently the highest-load requests (Read/Write)? (→ consider applying CQRS)
- Data distribution: Is there a risk of a hot spot where data concentrates on a particular key? (→ re-examine the sharding key)
- Transaction complexity: Is there business logic that spans multiple domains? (→ consider introducing the Saga pattern)
- Data types: Is all data tied to a relational DB? (→ consider introducing Polyglot Persistence)
If you follow this roadmap and gradually improve the architecture, you will be able to build a robust distributed system that goes beyond the limits of a single DB and can stably handle traffic from billions of users.
Frequently Asked Questions (FAQ)
Q1. Doesn’t applying sharding make data reads more difficult? A. Yes, sharding is fundamentally fastest for key-based lookups. If you frequently query by conditions where you don’t know the key (e.g., search by a particular user name), it is essential to introduce a separate search engine (Elasticsearch) and build a Read Model.
Q2. Doesn’t using the Saga pattern reduce data consistency? A. The definition of “consistency” changes. 2PC guarantees immediate consistency, while Saga guarantees a state that will eventually match over time (eventual consistency). If business requirements demand immediate consistency, use 2PC only for that logic, or split transaction boundaries into smaller pieces.
Q3. What should you consider first when applying sharding? A. First, identify the most frequently used query patterns, and finding a sharding key that can support those patterns most efficiently is the top priority. Rather than blindly introducing sharding, it is important to accurately diagnose the bottleneck.
Nodelog는 모든 콘텐츠의 내용과 출처를 공개 전에 검토합니다. 환경(OS·버전)에 따라 결과가 달라질 수 있는 기술 정보는 공식 문서와 함께 확인하며, 검토 기준과 정정 원칙은 편집 정책에서 안내합니다. 오류를 발견하시면 이메일로 제보해 주세요 — 확인 후 신속히 정정합니다.
Comments
Be the first to comment.