Architecture: How should R2 buckets be organized — per MongoDB database, p...

Documentation for Sessions

🏗️ Architecture: How should R2 buckets be organized — per MongoDB database, p...

Date: 2026-03-10
Time: 17:59:22 UTC
Session: gspace1-198.5
Agent: backend
Confidence: 93%
Status: ✅ Documented


📋 Decision Context

Question:

How should R2 buckets be organized — per MongoDB database, per space, or by domain?

Task: S198.1: Multimodal vision + Cloudflare R2 storage


🎯 Decision Made

Chosen:

6 buckets organized by domain boundaries with different lifecycle/access policies. NOT per-MongoDB-database (most DBs have zero binary data). NOT per-space (1000 bucket hard limit from Cloudflare). Space isolation via key prefixes using unique spaceSlug.

Options Considered:

  1. 1:1 R2 bucket per MongoDB database
  2. Per-space R2 bucket
  3. Single bucket with key prefixes
  4. Domain-based buckets (6) with spaceSlug key prefixes
  5. Match MongoDB databases selectively (only those with binary data)

💭 Reasoning

1:1 MongoDB mapping was rejected because most databases (ai-agents, ai-mcp-dev, ai-context, ai-memory, gograb-analytics, gograb-core, vitto-mind) contain zero binary data — creating empty buckets adds configuration overhead with no value. Per-space buckets hit Cloudflare's hard 1000 bucket limit. Domain-based buckets work because: different TTLs (chat-media permanent, gen 30d, backups 90d), different access control (assets admin-only, space-production rate-limited), different compliance (GDPR for end-user data). Space isolation achieved via spaceSlug key prefix — verified safe because spaceSlug has a unique MongoDB index with collision handling (appends timestamp). Future premium tenants get isolated gograb-tenant-{spaceId} buckets with separate credentials.


📁 Files Involved


🔗 Related


Auto-generated by MCP Smart Consolidation