Data Model
Both DPGs use PostgreSQL as their system of record (via Drizzle ORM) and Redis for caching, sessions and queues. They can run on the same PostgreSQL and Redis servers, but each DPG owns its own database and they do not share tables.
Signals data model
Section titled “Signals data model”The Signals database is organised around the item/action/event primitives:
| Entity | What it holds |
|---|---|
| Items | Versioned, schema-typed records keyed by item_type (e.g. profile_1.0). Item tables are partitioned so that high-volume reads can prune to relevant partitions. |
| Schema registry | The schemas that define networks and item types. Schemas are fetched and cached at the inter-instance read layer. |
| Actions & events | Interactions between items and their structured results. |
| Organisations | Carries a type column (network_service | aggregator | voice) that gates what each org may do (for example, only network_service orgs may upsert aggregators). |
How the item/action/event primitives relate:

Always query through the partition-aware helpers in @dpg/database; a query against the parent table without a partition key scans all partitions.
Schema files live in apps/api/db/postgres/schema/. Migrations are generated, never hand-edited — regenerate with pnpm db:generate:api. A bundled schema.sql is produced and verified with pnpm schema:bundle / pnpm schema:bundle:check.
Aggregator data model
Section titled “Aggregator data model”The Aggregator database (Drizzle, owned by apps/api) holds:
| Entity | What it holds |
|---|---|
| Aggregators | Registration state, approval status, profile data. |
| Participants | Onboarded individuals/enterprises destined to become Signals items. |
| Bulk jobs | Upload batches and per-row processing state for the worker. |
| Registration links & metrics | Shareable links and their roll-ups. |
db-schema is the single source of truth; apps import table definitions from it. Migrations are generated with pnpm --filter @aggregator-dpg/api db:generate and applied with db:migrate.
Design principles
Section titled “Design principles”- Schema-typed, never freeform. An item’s structure is governed by its
item_typeschema; clients cannot invent fields. - Backend-owned identity fields.
item_instance_urlanditem_schema_urlare generated server-side. - Configuration as code. No domain- or environment-specific value is hardcoded. Values load once at startup from config loaders or environment variables, and each network’s schemas live in their own folder (see Configuration).
Where to go next
Section titled “Where to go next”- Schema-Driven Model — how these tables are shaped by schemas rather than code.
- Read & Write Paths — how the data is actually queried and written.

