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.

Related