Two services that write to the same table are not two services. They’re one system with a confusing deployment topology.

The schema quietly becomes an API that everyone depends on and no one owns. A column rename turns into a cross-team incident. No service can enforce its own invariants, because another service can change the data underneath it at any moment. You have microservices on the org chart and a monolith in production.

The appeal is real — “just join the table” is faster to write than an API call, and a shared database is the path of least resistance. But you’ve traded an explicit, versionable interface for an implicit, brittle one. The coupling didn’t disappear; it went underground, where you can’t see it until it breaks.

Give each service its own store. Make cross-service data flow an explicit contract — a synchronous API or a published event — something you can version, observe, and reason about.