Overview
BrokerOS relies on PostgreSQL managed through Prisma 7. The schema located atpackages/prisma/schema.prisma serves as the single source of truth for the entire database architecture.
All database queries across apps/api and apps/workers use the strongly typed Prisma client generated to packages/prisma/generated/client and re-exported via @brokeros/prisma. Raw SQL strings are strictly prohibited in application code.
The Core Invariant (Project.isCpProject)
The BrokerOS platform hosts two completely distinct business models inside a single database instance:
- Internal Brokerage: Internal sales team sells developer inventory directly to prospective homebuyers. Projects are flagged with
isCpProject = false. - Channel Partner (CP): External broker network recruited by Sourcing Managers and closed by Closing Managers. Projects are flagged with
isCpProject = true.
Entity Relationship Overview
Telephony & Softphone Architecture Models
The database tracks both company-wide carrier infrastructure and individual softphone call sessions:1. CrmTelephonyConfig
Manages the organization’s active carrier connection configured at Dashboard -> Admin -> Settings -> CRM Telephony & WebRTC:
Single Active Carrier Rule: Only one
CrmTelephonyConfig record may have isActive = true at any given time. Connecting a new carrier automatically marks prior configurations inactive.2. CallRecord
Stores every inbound and outbound telecalling interaction, carrier identifiers, audio recording URLs, and AI intelligence:
Transaction Law (prisma.$transaction)
Multi-model writes must always execute inside an interactive transaction (prisma.$transaction) to guarantee atomicity. For example, converting a lead into a confirmed booking:
Soft-Delete Pattern
To comply with real estate regulatory requirements and maintain financial audit trails, entity records are never hard-deleted from the database:apps/api/ must explicitly append the filter:
deletedAt timestamps are excluded from active dashboards, search indexes, and campaign recipient pools while remaining intact for historical audit reporting.
Indexing & Performance Guidelines
The BrokerOS schema enforces indexes on frequently filtered fields:- Composite index on
[projectId, status, deletedAt]for fast lead pipeline queries - Index on
[phoneNumberId, createdAt]for incoming WhatsApp message lookups - Unique index on
[email, deletedAt]for customer deduplication - Indexes on foreign keys (
brokerId,assignedUserId,unitId) to optimize relational joins - Index on
providerCallIdfor fast lookup during carrier recording and status webhook callbacks - Composite index on
[status, scheduledAt]acrossWhatsAppMessage,EmailMessage, andSmsMessagemodels for sub-millisecond worker polling of queued messages
Omnichannel Scheduled Messaging Models
To support time-delayed 1-on-1 team inbox messaging across WhatsApp, SMS, and Email, each messaging table incorporates dedicated scheduling attributes:
All three models define
@@index([status, scheduledAt]) to ensure the background scanner worker performs non-blocking index scans every 10 seconds.