Roadmap Architecture Decisions - osama1998H/Moca GitHub Wiki
Architecture Decisions
Summary of key ADRs (Architecture Decision Records) from the Moca project.
ADR-001: PostgreSQL with AfterConnect for Tenant Isolation
Decision: Use AfterConnect callback to set search_path per tenant pool.
Context: Need schema-per-tenant isolation with pgxpool.
Outcome: Proven in MS-00 Spike 1. Per-site pools naturally isolate prepared statement caches.
ADR-002: Redis Streams for At-Least-Once Job Delivery
Decision: Use Redis Streams with consumer groups and XAutoClaim. Context: Need reliable background job processing with DLQ. Outcome: Proven in MS-00 Spike 2. ZADD for scheduled jobs.
ADR-003: Go Workspace for App Composition
Decision: Use go.work to compose framework + app modules.
Context: Apps need independent Go modules that can import framework packages.
Outcome: Proven in MS-00 Spike 3. MVS resolves correctly; replace directives as escape hatch.
ADR-005: Cobra CLI with init() Registration
Decision: Apps register CLI commands via init() + blank imports.
Context: CLI needs to be extensible by apps without compile-time coupling.
Outcome: Proven in MS-00 Spike 5. app:command namespace convention.
ADR-006: Meilisearch with Index-Per-Tenant
Decision: Meilisearch indexes named {site}_{doctype}.
Context: Need full-text search with tenant isolation.
Outcome: Proven in MS-00 Spike 6. waitForTask required for all writes. Tenant tokens for high-tenant-count.
ADR-007: Desk Distribution as npm Package
Decision: Distribute Desk as @osama1998h/desk npm package with Vite plugin.
Context: Projects need the framework desk without copying source code.
Outcome: Three-layer composition (framework -> app extensions -> project overrides).
Database Choice: PostgreSQL 16+ over CockroachDB
Decision: PostgreSQL 16+ with schema-per-tenant over CockroachDB. Rationale: Mature JSONB support, native RLS, lower operational complexity, proven at scale for multitenant SaaS.
Kafka-Optional with Redis Fallback
Decision: Kafka for durable event streaming, Redis pub/sub as fallback. Rationale: Small deployments shouldn't need Kafka. Redis pub/sub covers cache invalidation and real-time notifications.