0
0
MicroservicesComparisonIntermediate · 4 min read

Database per Service vs Shared Database: Key Differences and When to Use

In microservices, database per service means each service has its own database, ensuring strong isolation and independent scaling. A shared database is a single database accessed by multiple services, simplifying data management but risking tight coupling and harder scaling.
⚖️

Quick Comparison

This table summarizes the main differences between database per service and shared database approaches in microservices.

FactorDatabase per ServiceShared Database
Data IsolationStrong isolation; each service owns its dataWeak isolation; data shared among services
Service IndependenceHigh; services can evolve independentlyLow; changes affect multiple services
ScalingEasier to scale services and databases separatelyScaling is limited by single database capacity
Data ConsistencyEventual consistency; cross-service transactions complexStrong consistency; easier with single DB
ComplexityHigher operational complexity managing multiple DBsSimpler setup with one database
CouplingLoose coupling between servicesTight coupling due to shared data schema
⚖️

Key Differences

The database per service pattern assigns each microservice its own database. This means services are fully responsible for their data, allowing them to change schemas or database technologies without impacting others. It promotes loose coupling and independent deployment but requires handling data consistency across services, often using asynchronous messaging or events.

In contrast, the shared database approach uses a single database accessed by multiple services. This simplifies data management and ensures strong consistency with traditional transactions. However, it creates tight coupling between services, making schema changes risky and deployments less independent. It can also become a bottleneck for scaling.

Choosing between these depends on priorities like independence, consistency, and operational complexity. The database per service approach aligns better with microservices principles but demands more sophisticated data handling.

⚖️

Code Comparison

Example: A service saving a new user record using database per service approach with a dedicated database.

python
import sqlite3

class UserService:
    def __init__(self):
        self.conn = sqlite3.connect('user_service.db')
        self.create_table()

    def create_table(self):
        self.conn.execute('''CREATE TABLE IF NOT EXISTS users (
                             id INTEGER PRIMARY KEY AUTOINCREMENT,
                             name TEXT NOT NULL)''')
        self.conn.commit()

    def add_user(self, name: str):
        self.conn.execute('INSERT INTO users (name) VALUES (?)', (name,))
        self.conn.commit()
        return f"User '{name}' added."

service = UserService()
print(service.add_user('Alice'))
Output
User 'Alice' added.
↔️

Shared Database Equivalent

Example: Two services sharing the same database to add users and orders.

python
import sqlite3

class SharedDatabase:
    def __init__(self):
        self.conn = sqlite3.connect('shared.db')
        self.create_tables()

    def create_tables(self):
        self.conn.execute('''CREATE TABLE IF NOT EXISTS users (
                             id INTEGER PRIMARY KEY AUTOINCREMENT,
                             name TEXT NOT NULL)''')
        self.conn.execute('''CREATE TABLE IF NOT EXISTS orders (
                             id INTEGER PRIMARY KEY AUTOINCREMENT,
                             user_id INTEGER,
                             product TEXT NOT NULL)''')
        self.conn.commit()

    def add_user(self, name: str):
        self.conn.execute('INSERT INTO users (name) VALUES (?)', (name,))
        self.conn.commit()
        return f"User '{name}' added."

    def add_order(self, user_id: int, product: str):
        self.conn.execute('INSERT INTO orders (user_id, product) VALUES (?, ?)', (user_id, product))
        self.conn.commit()
        return f"Order for '{product}' added for user {user_id}."

shared_db = SharedDatabase()
print(shared_db.add_user('Alice'))
print(shared_db.add_order(1, 'Book'))
Output
User 'Alice' added. Order for 'Book' added for user 1.
🎯

When to Use Which

Choose database per service when you want strong service independence, scalability, and can handle eventual consistency with asynchronous communication. It fits well for large, complex systems where services evolve separately.

Choose shared database when you need strong consistency, simpler data management, and your system is small or legacy where tight coupling is acceptable. It reduces operational overhead but limits service autonomy.

Key Takeaways

Database per service offers strong isolation and independent scaling but requires handling data consistency carefully.
Shared database simplifies data consistency and management but creates tight coupling and scaling limits.
Choose database per service for scalable, loosely coupled microservices.
Choose shared database for simpler setups needing strong consistency and less operational complexity.
Understanding trade-offs helps design microservices that balance independence and data needs.