Skip to main content

Database Architecture

Overview

Single PostgreSQL RDS instance. After the Phase D.5 schema absorption (April 2026), the per-product schemas were consolidated into the divinux schema:

SchemaAppKey Entities
divinuxDivinuxStatus pages, components, incidents, subscribers, maintenance windows; alerts, alert events, teams, schedules, escalation policies, integrations (Slack/Teams/Discord), workflows; checks, check results, relays, aggregations; AI analyses, RCA documents, action items, deploy events
corePlatformOrganizations, members, users, subscriptions, product roles, SCIM tokens, analytics
situationsPlatformIncident coordination / situations
Legacy alerts.* tables

The Phase D.5 absorption moved the active per-product data into divinux, but some legacy alerts.* tables persist for backward compatibility. The standalone statuspages, alerts, and synthetics schemas are no longer the source of truth for new writes.

Core Schema Entities

The core schema contains entities shared across all products:

TableDescriptionKey Columns
core.organizationsOrganization recordsname, slug, branding
core.organization_membersOrg membershiprole, invite_status, invite_token, invited_at, accepted_at
core.usersUser profiles (synced from Cognito)cognito_sub, email, name, is_employee
core.subscriptionsLegacy per-user subscription recordsplan, status, stripe_customer_id
core.org_product_subscriptionsPer-product subscription per orgproduct, plan, status, trial dates
core.org_product_rolesPer-product role assignmentsproduct, role, user_id, organization_id
core.scim_tokensSCIM 2.0 provisioning tokenstoken_hash (SHA256), revoked_at
core.analytics_eventsProduct usage telemetryevent_type, product, metadata
core.user_activitiesLast-seen trackinglast_active_at, product

RDS Configuration

  • Engine: PostgreSQL 15
  • Instance: db.t3.micro (prod)
  • Multi-AZ: Enabled
  • Encryption: Enabled at rest
  • Backups: 7-day retention
  • Host: statux-prod-rds-main.c4540ua8ceif.us-east-1.rds.amazonaws.com

VPC Isolation

Database VPC (10.1.0.0/16) is fully private:

  • No internet gateway
  • Accessed via VPC peering from Application VPC
  • Bastion access via Access VPC (SSM port forwarding)

Connecting to Production DB

There is no SSH bastion. Use SSM port forwarding through an API EC2 instance:

# Find a running API instance
aws autoscaling describe-auto-scaling-groups \
--auto-scaling-group-name statux-prod-asg-divinux-api \
--query 'AutoScalingGroups[0].Instances[0].InstanceId' --output text

# Start port forwarding
aws ssm start-session \
--target <instance-id> \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters '{"host":["statux-prod-rds-main.c4540ua8ceif.us-east-1.rds.amazonaws.com"],"portNumber":["5432"],"localPortNumber":["5432"]}'

# Connect (in another terminal)
PGSSLMODE=require psql -h localhost -p 5432 -U <user> -d statux

DB password is in Secrets Manager (e.g., statux/divinux-api-config -> DATABASE_PASSWORD).

Migrations

The Divinux API manages its schema via TypeORM migrations:

npm run migration:generate:divinux   # Generate migration
npm run migration:run:divinux # Run migrations
npm run migration:show:divinux # Show applied/pending
npm run migration:revert:divinux # Revert the last migration
note

The Platform API (core / situations schemas) has no TypeORM migration scripts. Its situations.module applies idempotent DDL with IF NOT EXISTS SQL on boot, and core.migrations tracks the rest manually.