إنتقل إلى المحتوى الرئيسي

🗄️ Data Architecture

BayanCore's data architecture is designed to handle high-transaction workloads while enforcing strict tenant isolation, local data retention limits, and low-latency database queries.


1. Multi-Tenancy & Tenant Isolation

BayanCore utilizes a shared-database, row-level multi-tenancy model running on isolated container pools:

[Customer A Frontend] ──> [Tenant Gateway A] ──> [Shared MariaDB Instance]
├── Rows filtered by company = "Company_A"
[Customer B Frontend] ──> [Tenant Gateway B] ──> └── Rows filtered by company = "Company_B"
  • Logical Isolation: Every document (invoices, ledger entries, purchase orders, employees) is tagged with a mandatory company field.
  • Query Filtering: All SQL queries originating from user interfaces or background jobs are programmatically appended with a WHERE company = [tenant_company_id] filter by the Frappe framework layer.
  • Database Isolation for Enterprises: For enterprise-tier clients, the deployment system provisions dedicated MariaDB instances to guarantee complete physical data isolation.

2. Row-Level Security (RLS) & Permissions

User permission boundaries are enforced at the database row level:

  • Document-Level Permissions (Frappe User Roles): Access is controlled using Role-Based Access Control (RBAC). For example:
    • Sales Representatives can view and draft only invoices they created (owner = [user_id]).
    • Finance Managers can view all invoices but cannot edit them once posted.
    • Company Owners have global read-write permissions across all modules.
  • No Raw SQL Bypass: The experience layer communicates with the execution layer exclusively through API contracts. Direct raw SQL executions from user clients are programmatically blocked by the API Gateway.

3. Database Engine & Indexing (MariaDB)

MariaDB serves as our primary transactional database engine.

  • Partitioning & Indexing:
    • Compound indexes are defined on frequently queried tables to prevent full-table scans (e.g., invoice(company, posting_date, status)).
    • Audit log tables are partitioned by year to optimize search performance and simplify retention archives.
  • Dual Calendar Storage: Financial records store Gregorian dates natively (posting_date). The UI layer converts these dates to Hijri formats programmatically using the client's locale config, ensuring clean reporting alignment with local customs.

4. Redis Cache & Session Store

In-memory data structures are managed using OCI Cache (Redis):

  • Session Management: User session tokens (JWTs) are cached in Redis with strict time-to-live (TTL) expiries mapped to Clerk authentication limits.
  • Rate-Limit Buckets: IP-based and user-based API requests are throttled using Token Bucket algorithms stored in Redis sorted sets.
  • Metadata Caching: Frequently accessed, static compliance schemas (like ZATCA UBL schema templates) are cached in-memory, bypassing database queries during invoice validation.