Where Coupling Hides
Slices look independent in the architecture diagram. At runtime, coupling sneaks back in.
Shared Tables
The database is the truth. Multiple slices query the same tables.
| Symptom | Cause |
|---|---|
| Merge conflicts on migrations | Two features touch the same schema |
| "My query got slow" | Another feature's index change |
| Deployment ordering | Foreign key dependencies |
| Phantom reads | Concurrent updates across slices |
The table is the coupling point. Every feature reading users is coupled to every feature writing it.
Shared Streams
In traditional event sourcing, stream = consistency boundary.
Problem 1: Stream design locks in coupling
# Stream per entity type (User stream)
User-42: [UserCreated, AddressUpdated, CreditLimitSet, ...]
# Command needs to check credit across users?
# Now you need cross-stream coordination
Problem 2: All readers of a stream are coupled
User-42 stream
│
├─── Order slice (reads credit limit)
├─── Notification slice (reads email)
└─── Analytics slice (reads all)
# Schema change to UserCreated affects all three
Problem 3: Performance coupling
Hot streams (high-traffic entities) become bottlenecks. All commands on User-42 serialize through that stream's lock.
Shared Domain Models
The "DRY" reflex creates coupling:
// shared/domain/user.go
type User struct {
ID string
Email string
CreditLimit int // ← Added by feature A
Preferences Prefs // ← Added by feature B
}
Now features A and B share code. Merge conflicts. Version coordination. "Improvements" that break other slices.
Shared Event Schemas
// events/user.go
type UserCreated struct {
ID string
Email string
Name string // ← feature A adds this
}
Every consumer must handle Name. Schema evolution requires coordination.
The Pattern
Coupling appears wherever multiple slices reference the same:
- Table
- Stream
- Type definition
- Schema version
True independence means: no shared references.
The Solution
What if slices shared only one thing: the contract of what events exist?
- No shared tables
- No shared streams
- No shared types
- Just: "event X happened, here's its shape"