Shared Database and Shared Library Coupling

A practical lesson on how shared schemas and oversized shared libraries recreate hidden monolith behavior across supposedly separate services.

Shared database coupling is one of the clearest violations of service autonomy: several services depend directly on the same schema or tables, so changes to data shape ripple across boundaries immediately. Shared library coupling can create a similar problem in less obvious form. Teams centralize domain models, event contracts, or business rules in one common library, and suddenly supposedly independent services must move together whenever that shared model changes.

The two mechanisms look different. The architectural effect is similar. Hidden shared dependencies undermine local ownership and recreate monolith-style coupling through back doors.

    flowchart TD
	    A["Service A"] --> DB["Shared schema"]
	    B["Service B"] --> DB
	    C["Service C"] --> LIB["Shared domain library"]
	    D["Service D"] --> LIB
	    DB --> E["Coupled schema changes"]
	    LIB --> F["Coupled release and model changes"]

What to notice:

  • both patterns create central hidden dependencies
  • the coupling is not always visible in the service API alone
  • local autonomy disappears when internal models are shared too directly

Why Shared Databases Are So Damaging

When several services read and write the same schema:

  • no service truly owns the data model
  • schema changes require coordination
  • teams bypass published contracts
  • debugging becomes harder because direct reads hide dependencies

The architecture may still have service boundaries at the network level, but the real source of truth remains shared. That makes the service split less meaningful than it appears.

Shared Libraries Can Recreate the Same Problem

Shared libraries are not always harmful. Narrow infrastructure helpers can be useful:

  • logging adapters
  • tracing helpers
  • serialization utilities
  • retry wrappers

The danger appears when the shared library contains:

  • business rules
  • internal domain objects
  • event contracts with constant churn
  • validation logic that several services cannot evolve independently

At that point, the library acts like a hidden monolith module. The services may be separately deployed, but their internal model is still centrally controlled.

A Small Example of Dangerous Shared Logic

1// shared-domain/customer-status.ts
2export function canApplyDiscount(
3  loyaltyTier: string,
4  suspended: boolean,
5  accountAgeDays: number,
6): boolean {
7  return loyaltyTier === "gold" && !suspended && accountAgeDays > 30;
8}

What this demonstrates:

  • the code looks reusable
  • the logic is actually domain policy
  • if several services depend on this shared rule, they now move together when the policy changes

This is different from sharing a logger or metrics wrapper. The library is now defining domain truth across boundaries.

Why Teams Accept the Trade-Off

These anti-patterns often grow from convenience:

  • a report is urgent, so a team reads another service’s table directly
  • shared models reduce duplicate code today
  • a central schema feels easier than events or read models
  • a single library makes contracts look consistent

Each decision saves time locally. The cost appears later in release coupling, ownership confusion, and change paralysis.

Better Alternatives

Stronger alternatives include:

  • one service owning one source of truth
  • explicit APIs or events for cross-boundary interaction
  • narrow shared infrastructure libraries only
  • versioned contracts instead of one always-shared internal model
  • read models for consumer query needs

The principle is simple: share infrastructure carefully, but do not share domain ownership invisibly.

A Useful Review Record

1coupling_review:
2  direct_cross-service_table_access: true
3  shared_library_contains_domain_rules: true
4  schema_change_requires_multi-team_approval: true
5  contract_versioning_exists: false
6diagnosis_bias: hidden-monolith-coupling

What this demonstrates:

  • the anti-pattern often combines several forms of hidden dependency
  • the review should look beneath the public API layer
  • contract and ownership discipline are the real fixes

Design Review Question

A team argues that shared database access is acceptable because the services are still separately deployed, and shared business logic in a common library reduces duplication. What is the stronger architectural objection?

The stronger objection is that separate deployment is not enough if the services still depend on one shared schema or one shared domain model. The architecture is preserving the appearance of service boundaries while keeping the underlying ownership and change model centralized.

Quiz Time

Loading quiz…
Revised on Thursday, April 23, 2026