| Users | Services | Databases | Data Volume | Traffic | Complexity |
|---|---|---|---|---|---|
| 100 users | 5-10 | 5-10 small DBs | Low (MBs) | Low (few QPS) | Simple coordination |
| 10,000 users | 10-20 | 10-20 medium DBs | Medium (GBs) | Medium (hundreds QPS) | Need service discovery, monitoring |
| 1,000,000 users | 20-50 | 20-50 large DBs | High (TBs) | High (thousands QPS) | Complex data consistency, backups |
| 100,000,000 users | 50+ | 50+ very large DBs | Very High (PBs) | Very High (tens of thousands QPS) | Advanced sharding, cross-service sync |
Database per service pattern in Microservices - Scalability & System Analysis
Start learning this pattern below
Jump into concepts and practice - no test required
At small scale, the database for each service handles requests well. As users grow to thousands or millions, the first bottleneck is the database instance for a service. Each database can handle only so many queries per second (typically 5,000-10,000 QPS). When traffic grows, the database CPU, memory, or disk I/O saturates first.
Also, cross-service data consistency and communication overhead increase, causing latency and complexity.
- Horizontal scaling: Add more instances of the service and database replicas to distribute load.
- Read replicas: Use read-only replicas to offload read queries from the primary database.
- Database sharding: Split large databases by user ID or other keys to spread data and queries.
- Caching: Use in-memory caches (like Redis) to reduce database hits for frequent reads.
- Service isolation: Keep databases per service to avoid contention and allow independent scaling.
- Asynchronous communication: Use message queues to decouple services and reduce synchronous DB calls.
- Monitoring and automation: Track DB performance and automate scaling decisions.
Assuming 1 million users generating 10,000 QPS total:
- Each service DB handles ~200-500 QPS (if 20 services), within typical DB limits.
- Storage per DB: 1 TB for user data and logs.
- Network bandwidth: 10,000 QPS * 1 KB/request = ~10 MB/s total, manageable on 1 Gbps links.
- Cache layer reduces DB load by 30-50%, saving CPU and I/O.
- Adding replicas and shards increases infrastructure cost but improves availability and performance.
When discussing scalability for database per service pattern, start by explaining the isolation benefits. Then identify the database as the first bottleneck as traffic grows. Discuss how to horizontally scale databases with replicas and sharding. Mention caching and asynchronous communication to reduce load. Finally, highlight monitoring and automation for proactive scaling.
Question: Your database handles 1000 QPS. Traffic grows 10x to 10,000 QPS. What do you do first and why?
Answer: First, add read replicas to offload read queries from the primary database. This reduces CPU and I/O pressure. If writes also increase, consider sharding the database to distribute write load. Caching frequent reads can also help. This approach addresses the database bottleneck effectively.
Practice
Database per service pattern in microservices architecture?Solution
Step 1: Understand the pattern's goal
The Database per service pattern means each microservice owns its own database to avoid tight coupling.Step 2: Analyze the benefits
This independence allows each service to be developed, deployed, and scaled without affecting others.Final Answer:
Each service can be developed, deployed, and scaled independently. -> Option CQuick Check:
Service independence [OK]
- Thinking all services share one database
- Assuming database sharing improves independence
- Believing it reduces total databases
Solution
Step 1: Recall communication rules in this pattern
Services do not share databases; they communicate via APIs to maintain independence.Step 2: Identify correct data access method
Using APIs ensures loose coupling and clear service boundaries.Final Answer:
Use APIs to communicate and request data from other services. -> Option DQuick Check:
API communication [OK]
- Trying to query other service databases directly
- Assuming shared connection pools exist
- Using database triggers for cross-service sync
Solution
Step 1: Identify data ownership
InventoryService owns stock data in its own database; OrderService cannot access it directly.Step 2: Determine communication method
OrderService must call InventoryService's API to get current stock info.Final Answer:
OrderService sends an API request to InventoryService to get stock information. -> Option AQuick Check:
API call for data [OK]
- Direct DB queries between services
- Duplicating data in multiple databases
- Relying on push updates to other service DBs
Solution
Step 1: Identify incorrect practice
Directly querying another service's database breaks independence and can cause stale or inconsistent data.Step 2: Understand correct communication
Services should communicate via APIs to keep data consistent and boundaries clear.Final Answer:
Services are directly querying each other's databases. -> Option BQuick Check:
Direct DB queries cause inconsistency [OK]
- Assuming shared schema is the problem
- Thinking async API calls cause inconsistency
- Believing separate DBs cause inconsistency
Solution
Step 1: Understand distributed transaction challenges
Two-phase commit is complex and reduces service independence, so it's rarely used in microservices.Step 2: Identify best practice for consistency
Event-driven communication with eventual consistency and compensating actions allows services to stay independent and handle failures gracefully.Final Answer:
Implement eventual consistency using event-driven communication and compensating actions. -> Option AQuick Check:
Event-driven eventual consistency [OK]
- Trying distributed two-phase commit in microservices
- Sharing a single database defeats independence
- Periodic data copying causes stale data
