Architecture overview
Ticketra is a modular monolith: a single API process organized into domain modules, not a set of microservices. This keeps the deployment simple to run, reason about, and back up — for a solo analyst or a full SOC — while still enforcing clean internal boundaries.
The four containers
| Container | Responsibility |
|---|---|
| frontend | Nginx serving the React single-page app; reverse-proxies the API and SSE streams; applies security headers. |
| api | The Express + TypeScript application: all business logic, auth, and integrations. |
| postgres | PostgreSQL 16 — the source of truth for all data. |
| opensearch | A secondary, rebuildable full-text search index. |
OpenSearch is an index you can rebuild from PostgreSQL at any time. If search and the database ever disagree, the database wins.
How the modules talk
Within the API, domain modules (auth, cases, observables, audit, integrations, and more) communicate over an in-process event bus — not HTTP calls between services. This keeps cross-module coupling explicit and testable while avoiding network overhead.
Real-time features — live case updates and analyst presence — are delivered to browsers over Server-Sent Events (SSE), not WebSockets.
Data & security model at a glance
- No ORM: all database access is raw, parameterized SQL.
- Tenant isolation is enforced at both the API and database query level.
- Audit log is append-only.
- Secrets are read from Docker secrets, never hardcoded.
- Air-gap compatible: no runtime dependency on external CDNs or services.
For the deployment-facing security details, see the Hardening guide. For the isolation rules, see Multi-tenancy.