Skip to main content

Architecture Overview

Fataplus uses a sophisticated multi-tenant architecture that isolates client data while enabling seamless collaboration. Each project operates as a logical tenant with dedicated resources and access controls.
Unlike traditional SaaS multi-tenancy where each customer is a tenant, Fataplus uses project-based tenancy where each client project becomes its own isolated workspace.

How Multi-Tenancy Works

Project-Based Isolation

Each project receives:
  • Unique project ID (e.g., FP-2025-X7K9M3P1A)
  • Isolated data storage in PostgreSQL with row-level security
  • Dedicated subdomain access ([project-id].fata.plus)
  • Project-specific permissions and roles
  • Separate document storage namespace

Data Isolation

Complete separation of project data at the database level

Access Control

Role-based permissions unique to each project

Subdomain Routing

Custom URLs for direct project access

Resource Allocation

Independent storage and compute resources

Subdomain Routing

Dynamic Subdomain System

Fataplus implements intelligent subdomain routing for seamless access.
Primary Access Points
fata.plus              → Marketing website and agency portfolio
fata.pro               → CRM dashboard and project management
bknd.fata.plus         → Backend API and services
Infrastructure
  • Hosted on Cloudflare Pages (frontend)
  • Cloudflare Workers (backend API)
  • Astro + React frontend framework
  • Hono backend framework

Routing Configuration

The system uses Cloudflare’s edge routing for performance.
// Backend routing logic (simplified)
export default {
  async fetch(request: Request, env: Env) {
    const url = new URL(request.url);
    const hostname = url.hostname;
    
    // Extract tenant from subdomain
    const subdomain = hostname.split('.')[0];
    
    // Route to appropriate tenant context
    if (subdomain.startsWith('FP-')) {
      return handleTenantRequest(request, subdomain, env);
    }
    
    // Route to main application
    return handleMainRequest(request, env);
  }
};

Data Separation

Database Architecture

Fataplus uses shared database with logical separation for optimal performance and cost.
Tenant IdentificationEvery table includes tenant context:
CREATE TABLE projects (
  id VARCHAR(50) PRIMARY KEY,  -- Project ID is tenant ID
  project_name VARCHAR(255),
  status VARCHAR(50),
  client_id INTEGER,
  -- ... other fields
);

CREATE TABLE documents (
  id SERIAL PRIMARY KEY,
  project_id VARCHAR(50) REFERENCES projects(id),
  title VARCHAR(255),
  -- ... other fields
);

CREATE TABLE messages (
  id SERIAL PRIMARY KEY,
  project_id VARCHAR(50) REFERENCES projects(id),
  sender_id INTEGER,
  -- ... other fields
);
All queries are automatically scoped by project_id to ensure isolation.
PostgreSQL RLS PoliciesEnforce data access at the database level:
-- Enable RLS on documents table
ALTER TABLE documents ENABLE ROW LEVEL SECURITY;

-- Policy: Users can only access documents for their projects
CREATE POLICY project_documents_access ON documents
  FOR ALL
  USING (
    project_id IN (
      SELECT id FROM projects
      WHERE client_id = current_user_id()
      OR project_manager_id = current_user_id()
    )
  );
RLS policies provide defense-in-depth security even if application-level checks fail.
Cloudflare R2 / AWS S3 Structure
fataplus-storage/
├── FP-2025-X7K9M3P1A/
│   ├── documents/
│   │   ├── prd-v1.0.pdf
│   │   ├── tdr-v1.0.pdf
│   │   └── contract-signed.pdf
│   └── attachments/
│       └── design-mockup.fig
├── FP-2025-Y8L2N4Q5B/
│   └── documents/
└── ...
Access Control
  • Presigned URLs for secure downloads
  • Time-limited access tokens
  • IP-based restrictions (optional)
  • Encryption at rest

Tenant Provisioning

Automated Project Creation

When a client submits the intake form, the system automatically provisions a new tenant.
1

Form Submission

Client completes the smart intake form with project details.
// POST /api/submit
{
  "projectTitle": "Agritech Mobile App",
  "companyName": "AgriCorp SARLU",
  "contactEmail": "contact@agricorp.mg",
  // ... other fields
}
2

Tenant Creation

System generates unique project ID and creates tenant.
const projectId = `FP-${new Date().getFullYear()}-${generateUniqueId()}`;
// Result: FP-2025-X7K9M3P1A

// Create project record
await db.projects.create({
  id: projectId,
  projectName: data.projectTitle,
  status: 'intake',
  // ...
});
3

Resource Allocation

  • Create database entries with project_id
  • Initialize file storage bucket
  • Set up access control policies
  • Configure subdomain routing
4

User Provisioning

Create or link user accounts:
// Create client account if new
const client = await createOrUpdateUser({
  email: data.contactEmail,
  firstName: data.contactName.split(' ')[0],
  lastName: data.contactName.split(' ')[1],
  company: data.companyName,
  role: 'client'
});

// Link to project
await linkUserToProject(client.id, projectId);
5

Welcome Email

Send credentials and access information:
  • Project portal URL: https://${projectId}.fata.plus
  • Temporary password (requires reset on first login)
  • Quick start guide
  • Project manager contact

Access Control and Permissions

Role-Based Access Control (RBAC)

Each project has three primary roles with distinct permissions.
Permissions
  • ✅ View project details and status
  • ✅ Download client-facing documents
  • ✅ Send messages to project manager
  • ✅ Upload requested files
  • ❌ Edit project details
  • ❌ View internal documents
  • ❌ Manage team members
Use Case: Client stakeholders reviewing project progress

Permission Implementation

interface UserPermissions {
  canViewProjects: boolean;
  canEditProjects: boolean;
  canViewDocuments: boolean;
  canUploadDocuments: boolean;
  canSendMessage: boolean;
  canManageUsers: boolean;
}

const rolePermissions: Record<UserRole, UserPermissions> = {
  client: {
    canViewProjects: true,
    canEditProjects: false,
    canViewDocuments: true,  // Client-facing only
    canUploadDocuments: false,
    canSendMessage: true,
    canManageUsers: false,
  },
  'project-manager': {
    canViewProjects: true,
    canEditProjects: true,
    canViewDocuments: true,
    canUploadDocuments: true,
    canSendMessage: true,
    canManageUsers: false,
  },
  admin: {
    canViewProjects: true,
    canEditProjects: true,
    canViewDocuments: true,
    canUploadDocuments: true,
    canSendMessage: true,
    canManageUsers: true,
  },
};

Security Measures

Authentication

  • OAuth2 with Cloudflare Access
  • JWT token-based sessions
  • Password strength requirements
  • Multi-factor authentication (optional)

Authorization

  • Role-based access control
  • Resource-level permissions
  • Database row-level security
  • API endpoint protection

Data Protection

  • Encryption at rest and in transit
  • HTTPS enforcement (TLS 1.3)
  • Regular security audits
  • GDPR compliance measures

Network Security

  • Cloudflare WAF protection
  • DDoS mitigation
  • Rate limiting on APIs
  • Zero Trust architecture

Performance Optimization

Caching Strategy

Edge Caching
  • Static assets cached on Cloudflare CDN
  • Project data cached for 1 hour (configurable)
  • Invalidation on updates
Database Query Optimization
// Indexed queries for tenant isolation
CREATE INDEX idx_documents_project_id ON documents(project_id);
CREATE INDEX idx_messages_project_id ON messages(project_id);
CREATE INDEX idx_users_email ON users(email);
API Response Caching
export const revalidate = 3600; // 1 hour cache

Monitoring and Observability

Per-Project Tracking
  • Storage usage
  • API call volume
  • Active user count
  • Document access frequency
  • Message volume
Platform-Wide Monitoring
  • Total active tenants
  • Database connection pool usage
  • API response times
  • Error rates by tenant
  • Resource utilization

Next Steps

CRM Overview

Explore the full CRM system capabilities

Smart Forms

Learn about automated project intake

Collaboration

Discover agency partner workflows

AI Features

See how AI enhances the platform