Overview
Exowpee uses PostgreSQL 16 as its database engine. The schema spans 6 application-level migrations and 86+ package-level migrations, creating a comprehensive relational model for multi-tenant ERP operations.Core design principles
1. KSUID primary keys
All tables use KSUID (K-Sortable Unique Identifier) strings as primary keys instead of auto-incrementing integers. KSUIDs are 27-character strings that are:- Globally unique — No collisions across tables or databases
- Time-sortable — Newer records sort after older ones
- URL-safe — Can be used directly in API paths
39WSvi21oTnZN8i028Y80FTNT1x
The KsuidTrait in packages/shared/ automatically generates KSUIDs:
2. Multi-tenant scoping
Tables are scoped at two levels:3. Soft deletes
Many models use Laravel’sSoftDeletes trait, adding a deleted_at column. Records are never truly deleted — they’re marked as deleted and filtered from queries.
Key tables by domain
Identity & Access (IAM)
Team & Organization
Catalog
Products and categories have both
company_id and organization_id. The organization_id enables catalog sharing across all companies, while company_id tracks which company created the item.Orders
Ledger
Customers
Migrations
Where migrations live
All package migrations are auto-loaded by each package’s
ServiceProvider.
Running migrations
PostgreSQL procedures
Custom PostgreSQL stored procedures live indatabase/procedures/:
cashing_range_list.pgsql— Generates cashing (payment) reports by date range
Seeders
Optimistic locking
The Ledger package uses optimistic locking via theOptimisticLockingTrait from the shared package. Each record has a version column that’s checked on update to prevent concurrent modification conflicts: