ā ļø PRELIMINARY DOCUMENTATION - NEEDS REVIEW
Note: This documentation was created with assumptions about the project architecture and technology stack. It requires review and correction based on the actual implementation.
This document will be reworked once the project is closer to final release.
If you notice inaccuracies (e.g., assumed AWS/CDN usage, incorrect tech stack), please flag them so this can be updated with actual project details.
Technical overview of Flash Turbo CMS multi-tenant architecture.
Flash Turbo CMS is a multi-tenant SaaS platform where multiple independent stores (tenants) run on shared infrastructure while maintaining complete data isolation.
graph TB
subgraph Internet["š Internet"]
Customer["Customers"]
Admin["Store Admins"]
end
subgraph CDN["Content Delivery Network"]
CloudFront["AWS CloudFront"]
end
subgraph Frontend["Next.js Apps"]
Store1["Tenant 1 Store"]
Store2["Tenant 2 Store"]
Manager["Manager/Admin UI"]
end
subgraph Backend["Payload CMS Backend"]
Auth["Authentication"]
Collections["Collections API"]
Media["Media Manager"]
end
subgraph Database["Data Layer"]
MongoDB["MongoDB"]
Cache["Redis Cache"]
S3["AWS S3 Storage"]
end
Customer -->|Browse| CloudFront
Admin -->|Manage| Manager
CloudFront --> Store1
CloudFront --> Store2
Store1 --> Backend
Store2 --> Backend
Manager --> Backend
Backend --> Auth
Backend --> Collections
Backend --> Media
Collections --> MongoDB
Auth --> MongoDB
Media --> S3
Collections --> Cache
Each request identifies the tenant from:
tenant1.yourdomain.com vs tenant2.yourdomain.comstore1 vs store2/tenant1/dashboard vs /tenant2/dashboardEvery collection includes a tenantId or tenantKey field:
// Products collection
{
id: "prod_123",
name: "Coffee Beans",
tenantId: "tenant_abc", // ā Tenant isolation
price: 29.99,
createdAt: "2025-01-01T00:00:00Z"
}
Access Control:
// Only return products for current tenant
const products = await db.collection('products').find({
tenantId: getCurrentTenantId() // ā Enforced in queries
});
tenantId for performanceTenant Store (apps/multi-store/)
Tenant Manager (apps/multi-store/app/(manager)/)
Shared Components (apps/multi-store/src/components/)
Collections (Data Models):
Endpoints (Custom APIs):
Plugins (Extensions):
Collections (MongoDB):
tenantId for queriesPerformance:
Purpose: Speed up repeated queries
Strategy: Tenant-specific cache keys
// Cache key format
const key = `tenant_${tenantId}_products_${productId}`;
Invalidation: When data changes, clear tenant's cache
Purpose: Store product images, documents, files
Organization:
s3://bucket/
āāā tenant_abc/
ā āāā products/
ā āāā orders/
ā āāā uploads/
āāā tenant_xyz/
ā āāā products/
ā āāā orders/
ā āāā uploads/
Access Control:
sequence
Customer->>CDN: GET /products
CDN->>Store: Return cached page
Store->>API: GET /api/products
API->>Auth: Resolve tenant from domain
Auth->>DB: Query products WHERE tenantId=ABC
DB->>Cache: Check cache
Cache-->>DB: Cache hit/miss
DB->>Store: Return products
Store->>Customer: Render page with products
sequence
Admin->>Manager: Fill product form
Manager->>API: POST /collections/products
API->>Auth: Verify admin of tenant ABC
Auth->>Validator: Validate product data
Validator->>DB: Insert with tenantId=ABC
DB->>Cache: Invalidate product cache
Cache->>Revalidation: Trigger revalidation
Revalidation->>CDN: Purge old page cache
API->>Manager: Return created product
Manager->>Admin: Show success
ā No data leaks
ā Access control
ā Rate limiting
ā ļø SQL Injection
ā ļø Cache poisoning
ā ļø File access
Index Strategy
db.products.createIndex({ tenantId: 1, name: 1 })
Query Pattern
// Always lead with tenantId
await db.products.find({
tenantId: "tenant_abc", // ā First
status: "published"
})
Avoiding N+1 Queries
Cache Keys
tenant_{id}_{entity}_{pk}
tenant_abc_products_123
TTL (Time To Live)
Invalidation
Currently: Single MongoDB instance Future: MongoDB sharding by tenant
// Shard key ensures tenant locality
db.products.createIndex({ tenantId: "hashed" })
Last Updated: October 27, 2025 Version: 1.0 Status: ā Production Ready