ADR 0029 — Shared MongoDB instance with separate collections per service
Status
Accepted
Context
In a microservices architecture, the ideal pattern is “database per service” where each service owns its data store completely. This provides:
- Strong encapsulation and autonomy
- Independent scaling
- Technology freedom (different DBs for different services)
- No coupling through shared data
However, for this educational chatbot project (TFG), we have practical constraints:
- Resource limitations: Running multiple MongoDB instances increases infrastructure complexity and cost
- Development simplicity: A single MongoDB simplifies local development and CI/CD
- Data volume: The expected data volume doesn’t justify separate instances
- Operational overhead: Managing multiple databases adds complexity without proportional benefit
Currently, two services access MongoDB:
- backend: Manages
usersandsessionscollections (auth and session persistence) - chatbot: Manages
guiascollection (teaching guides) and LangGraph checkpoints
Decision
Use a single shared MongoDB instance with logically separated collections per service. Each service owns specific collections and no service directly accesses another service’s collections.
Collection Ownership
| Service | Collections | Purpose |
|---|---|---|
| backend | users, sessions | Authentication, user management, chat sessions |
| chatbot | guias, checkpoints | Teaching guide storage, LangGraph state persistence |
Rules
- No cross-service collection access: Backend must NOT query
guias; chatbot must NOT queryusers - Service-to-service communication via API: If backend needs teaching guide data, it calls chatbot’s API
- Consistent database name: Both services use
tfg_chatbotdatabase (configurable viaDB_NAME/MONGO_DB) - Independent connection management: Each service manages its own
MongoDBClientinstance
Configuration
# backend/config.py
db_name: str = "tfg_chatbot"
# chatbot/config.py
mongo_db: str = "tfg_chatbot"
Consequences
Positive
- Simpler infrastructure: One MongoDB container instead of multiple
- Easier development: Single connection string, simpler docker-compose
- Cost effective: Appropriate for TFG scope and educational context
- Clear ownership: Each service knows exactly which collections it owns
Negative
- Shared failure domain: MongoDB downtime affects all services
- Coordination required: Schema changes need awareness across teams
- Not pure microservices: Violates strict “database per service” principle
- Potential for drift: Risk of accidentally accessing wrong collections
Mitigations
- Document collection ownership clearly (this ADR)
- Code review to prevent cross-collection access
- Consider collection prefixes in future (e.g.,
backend_users,chatbot_guias) - Add integration tests to verify service isolation
Alternatives considered
Option A: Separate MongoDB instances per service
Pros:
- Pure microservices pattern
- Complete isolation
- Independent scaling
Cons:
- Higher resource usage
- More complex infrastructure
- Overkill for current scale
Option B: Shared database with no ownership rules (rejected)
Pros:
- Maximum simplicity
Cons:
- Tight coupling
- No clear boundaries
- Maintenance nightmare
Option C: Shared instance with separate databases (considered)
Pros:
- Logical separation at database level
- Same infrastructure simplicity
Cons:
- Still shares failure domain
- Marginal benefit over collection separation
- Slightly more complex connection strings
Option D: Shared instance with collection ownership (chosen)
Pros:
- Simple infrastructure
- Clear logical boundaries
- Appropriate for project scope
- Easy to migrate to Option A later if needed
Cons:
- Requires discipline to maintain boundaries
- Not pure microservices