Architecture & Technology
Master architecture for Palmyra ERP — a SaaS ERP designed to be manageable by a single developer. Multi-tenant, configuration-driven, one codebase for all industries.
Vision
Palmyra ERP is a multi-tenant SaaS ERP supporting manufacturing, retail, EBO, apparel, agriculture, import/export. It is configuration-driven — business rules, workflows, and industry-specific behavior are stored in the database, not in code.
Technology stack
| Layer | Technology | Notes |
|---|---|---|
| Server | C# .NET Core 8+ | Single solution, minimal projects |
| Web | MVC Razor Pages | Server-side layout, shell, initial render |
| API | MVC REST API | JSON request/response; all data via REST |
| Client | Vue.js 3 + PrimeVue | Mounted on Razor; fetches via REST |
| Database | PostgreSQL | Multi-tenant; config in DB |
| Data access | Npgsql (direct SQL) | No ORM — DbService / CrudService |
| Cache | In-memory (IMemoryCache) | PostgreSQL NOTIFY invalidation |
| Auth | JWT + Google Sign-In | Role-based access |
Multi-tenant architecture
Default: shared DB with tenant_id on every table. CrudService auto-filters WHERE tenant_id = @tenant_id. Tenant resolved from subdomain, X-Tenant-Id header, or JWT claim.
Hierarchy
Tenant → Company (legal entity) → Branch (location). All transactions scoped by tenant_id → company_id → branch_id. Inter-company transactions supported.
Database design
tenant_idon every table; CrudService auto-filters.company_id,branch_idfor multi-company.- Soft delete (
is_deleted); audit columns on every table. - PostgreSQL JSONB for flexible config/matrix data.
- No C# entity classes — data as
Dictionary<string, object?>.
API design
REST: GET/POST/PUT/DELETE /api/{module}/{resource}. List: ?page=1&pageSize=25. Action: POST /api/{module}/{resource}/{id}/{action}. Status codes: 200, 304, 400, 401, 403, 404, 500.