DEV Community

hadisa norozi
hadisa norozi

Posted on

Data Wars in Microservices: The Battle Between Isolation, Sharing, and Scalability

n a microservices architecture, how services manage and share data is a critical design decision that has a significant impact on the system's overall health and scalability. The core principle of microservices is loose coupling and high cohesion, which means each service should be an independent, self-contained unit responsible for its own data.

  1. Database per Service (Private Database)
    This is the most common and recommended pattern for microservices. Each microservice has its own private, isolated database. Other services can only access a service's data through its public API.

    • Schema per service: Each microservice has its own dedicated schema within a single database server. This is a good way to achieve logical separation while potentially sharing a single physical server for cost efficiency.
    • Database server per service: Each microservice has its own dedicated database server instance. This offers the highest level of isolation and control.
    • Private-tables-per-service: Each service owns a set of tables within a shared database, and access is restricted through database-level permissions. This is a less ideal approach as it can lead to coupling if not strictly enforced.

Advantages:
• Loose Coupling: Services are completely decoupled at the data level. A schema change in one service's database has no impact on other services.
• Independent Development and Deployment: Teams can work on their service and make changes to their database schema without coordinating with other teams.
• Technology Freedom (Polyglot Persistence): Each service can choose the type of database that best suits its needs (e.g., a relational database for a service that needs ACID transactions, a NoSQL document database for a service with unstructured data).
• Improved Scalability and Fault Tolerance: You can scale each service's database independently based on its specific load requirements. If one service's database fails, it doesn't bring down the entire system.

Disadvantages:
• Data Consistency Challenges: Implementing business transactions that span multiple services becomes complex. Traditional ACID transactions are no longer possible. You must use patterns like the Saga pattern to achieve eventual consistency.
• Complex Queries and Joins: Queries that need to join data from multiple services (e.g., "find all customers in a specific region and their recent orders") become difficult. You have to use API composition or other aggregation patterns to retrieve data from different services and combine it in the application layer.
• Increased Operational Complexity: You have to manage and operate multiple database instances, which can increase overhead for backups, monitoring, and scaling.

  1. Shared Database (Anti-Pattern) In this pattern, multiple microservices share a single database instance and its schema. This is often seen in monolithic-to-microservice migration strategies or when teams are first starting with microservices.

Advantages:
• Simplicity and Familiarity: This is the traditional approach from monolithic applications. It's easy to get started with and developers are often familiar with the concepts.
• ACID Transactions: You can easily use ACID transactions across multiple tables, as all data is in a single database.
• Simplified Queries: Queries that involve joins across multiple tables are straightforward.
• Reduced Operational Overhead: You only have one database to manage, which can simplify administration.

Disadvantages:
• Tight Coupling: This is the biggest drawback. Any change to the database schema by one service can break other services that depend on the same data.
• Loss of Autonomy: Teams cannot independently deploy their services because a database change might require coordinated deployments.
• No Technology Freedom: All services must use the same database technology. This limits your ability to use the best tool for each specific job.
• Single Point of Failure: If the shared database goes down, the entire system is affected.
• Scalability Bottleneck: The shared database can become a performance bottleneck as all services compete for the same resources.

  1. Schema Share (Hybrid Approach) "Schema share" can be a bit of a nuanced term, but it typically refers to a situation where multiple services share a single physical database but have their own, dedicated schemas within it. This is a good way to bridge the gap between the "shared database" anti-pattern and the full "database per service" model. The key distinction is that while the physical database is shared, the logical separation is maintained. Each service has a private schema, and other services are not supposed to directly access tables in another service's schema.

Advantages:
• Logical Decoupling: It provides a level of logical separation, so schema changes within one service's private schema don't directly affect others.
• Cost Efficiency: You can save on infrastructure costs by running a single, powerful database instance instead of many small ones.
• Reduced Operational Complexity: Managing one database server is simpler than managing many.

Disadvantages:
• Potential for Accidental Coupling: Without strict access controls, it's easy for developers to accidentally read from another service's schema, leading to tight coupling.
• Resource Contention: Services still compete for the same database resources (CPU, memory, I/O). A slow query from one service can impact the performance of all other services.
• Still a Single Point of Failure: While logical separation exists, the single physical database is still a single point of failure.

Summary and Other Types of Data Sharing
In summary, the Database per Service pattern is the gold standard for microservices as it fully supports the core principles of the architecture. The Shared Database is considered an anti-pattern because it violates these principles. The Schema per Service approach is a good middle ground that provides logical isolation while offering some operational benefits.
Beyond direct database access, microservices often share data in other ways, such as:
• API Composition: A service calls other services' APIs to get the data it needs.
• Event-Driven Architecture: Services publish events (e.g., "OrderCreated") to a message broker, and other services that need that data (e.g., a shipping service) can consume and react to those events.
• Data Duplication/Replication: Services can maintain a local, read-only copy of data from other services to improve performance and avoid direct API calls. This is a trade-off that introduces the challenge of eventual consistency.

Top comments (0)