Incident Response
Severity Levels
| Level | Description | Examples | Response Time | Escalation |
|---|---|---|---|---|
| P1 | Full service outage | All APIs unreachable, database down, complete data loss | Immediate | All hands, notify leadership within 15 min |
| P2 | Major degradation | Single API down, high error rate (>5%), billing failures | < 30 minutes | On-call engineer + team lead |
| P3 | Partial degradation | Elevated latency, intermittent errors, single feature broken | < 2 hours | On-call engineer |
| P4 | Minor issue | Cosmetic bug, non-critical feature, documentation error | < 24 hours | Normal sprint workflow |
Escalation Criteria
Escalate from P3 to P2 if:
- Issue persists for more than 30 minutes
- More than 3 customers report the issue
- Error rate exceeds 5%
Escalate from P2 to P1 if:
- Multiple services are affected
- Data integrity is at risk
- Issue persists for more than 15 minutes without a mitigation path
Response Steps
- Acknowledge - Note the time and initial symptoms
- Assess - Check health endpoints, logs, metrics
- Communicate - Update stakeholders and status page
- Mitigate - Rollback, restart, or apply fix
- Resolve - Confirm service restored
- Post-mortem - Document root cause and action items
Step 1: Initial Assessment
Check Health Endpoints
export AWS_PROFILE=statux-main
# Check all API health endpoints
# statuspage-api/alerts-api/synthetics-api/insights-api all folded into divinux-api (C5/D5/E5, 2026-05)
curl -s https://divinux-api.statux.io/api/v1/health | jq .
curl -s https://platform-api.statux.io/api/v1/health | jq .
Check ALB Target Health
# Get target group ARNs (check each API)
aws elbv2 describe-target-groups \
--query 'TargetGroups[*].[TargetGroupName,TargetGroupArn]' \
--output table
# Check target health for a specific target group
aws elbv2 describe-target-health \
--target-group-arn <target-group-arn>
Check Docker Logs via SSM
# List running instances (use the target ASG: statux-prod-asg-divinux-api or statux-prod-asg-platform-api)
aws ec2 describe-instances \
--filters "Name=tag:aws:autoscaling:groupName,Values=statux-prod-asg-divinux-api" \
--query 'Reservations[*].Instances[*].[InstanceId,State.Name,PrivateIpAddress]' \
--output table
# Get Docker logs from an instance
aws ssm send-command \
--instance-ids <instance-id> \
--document-name "AWS-RunShellScript" \
--parameters 'commands=["docker logs statux-api --tail 200 --since 10m"]'
# Retrieve the command output
aws ssm get-command-invocation \
--command-id <command-id> \
--instance-id <instance-id> \
--query 'StandardOutputContent' \
--output text
Two containers serve all of prod since the C5/D5/E5 folds (2026-05):
- Divinux (alerting + synthetics + statuspages + insights surfaces):
statux-divinux-api - Platform (orgs, members, situations):
statux-platform-api
Check RDS Connectivity
# Check RDS instance status
aws rds describe-db-instances \
--db-instance-identifier statux-prod-rds \
--query 'DBInstances[0].[DBInstanceStatus,Endpoint.Address,DBInstanceClass]' \
--output table
# Check active connections (via bastion or SSM)
psql -h <rds-endpoint> -U statux_admin -d statux -c \
"SELECT datname, numbackends FROM pg_stat_database WHERE datname = 'statux';"
# Check for long-running queries
psql -h <rds-endpoint> -U statux_admin -d statux -c \
"SELECT pid, now() - pg_stat_activity.query_start AS duration, query
FROM pg_stat_activity
WHERE state != 'idle' AND now() - pg_stat_activity.query_start > interval '30 seconds'
ORDER BY duration DESC;"
Step 2: Per-Service Troubleshooting
Since the C5/D5/E5 folds (May 2026) there are two API services in prod: Divinux (which serves the alerting, synthetics, statuspages, and insights surfaces) and Platform.
Divinux API (Port 3003)
Serves alerting, synthetics, statuspages, and AI insights. Container: statux-divinux-api. ASG: statux-prod-asg-divinux-api.
Common issues:
- Alert delivery delays (SMS/voice via AWS End User Messaging, push notifications)
- Escalation chain failures; high alert volume causing queue backlog
- Synthetic check execution timeouts, relay disconnections, region-network false positives
- Subscriber email delivery failures; incident webhook delivery timeouts
- AWS Bedrock throttling or timeouts; webhook ingestion failures; usage budget exceeded
What to check:
# Check the ASG
aws autoscaling describe-auto-scaling-groups \
--auto-scaling-group-names statux-prod-asg-divinux-api \
--query 'AutoScalingGroups[0].[DesiredCapacity,MinSize,MaxSize,Instances[*].HealthStatus]'
# Docker logs
aws ssm send-command --instance-ids <id> \
--document-name "AWS-RunShellScript" \
--parameters 'commands=["docker logs statux-divinux-api --tail 100 --since 5m 2>&1 | grep -i error"]'
Platform API (Port 3004)
Serves orgs, members, situations, billing, and SSO/SCIM. Container: statux-platform-api. ASG: statux-prod-asg-platform-api.
Common issues:
- Stripe webhook delivery failures
- Cognito authentication issues
- SCIM provisioning errors
What to check:
# Docker logs
aws ssm send-command --instance-ids <id> \
--document-name "AWS-RunShellScript" \
--parameters 'commands=["docker logs statux-platform-api --tail 100 --since 5m 2>&1 | grep -i error"]'
Step 3: Rollback Procedures
Quick Rollback (ASG Instance Refresh)
If a recent deployment caused the issue, roll back to the previous Docker image:
# 1. Find the previous working image tag
aws ecr describe-images \
--repository-name <ecr-repo-name> \
--query 'sort_by(imageDetails,&imagePushedAt)[-5:].imageTags' \
--output table
# 2. Tag the previous good image as "latest"
GOOD_TAG="<previous-sha>"
REPO="255982108053.dkr.ecr.us-east-1.amazonaws.com/<ecr-repo-name>"
# Pull, retag, and push
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 255982108053.dkr.ecr.us-east-1.amazonaws.com
docker pull $REPO:$GOOD_TAG
docker tag $REPO:$GOOD_TAG $REPO:latest
docker push $REPO:latest
# 3. Trigger instance refresh
aws autoscaling start-instance-refresh \
--auto-scaling-group-name <asg-name> \
--preferences '{"MinHealthyPercentage":50,"InstanceWarmup":120}'
# 4. Monitor the refresh
watch -n 10 'aws autoscaling describe-instance-refreshes \
--auto-scaling-group-name <asg-name> \
--query "InstanceRefreshes[0].[Status,PercentageComplete]" \
--output text'
ECR Repository and ASG Names
| App | ECR Repo | ASG Name |
|---|---|---|
| Divinux | statux-divinux-api | statux-prod-asg-divinux-api |
| Platform | statux-platform-api | statux-prod-asg-platform-api |
Database Rollback
If the issue is caused by a bad migration:
# 1. Take a snapshot before reverting
aws rds create-db-snapshot \
--db-instance-identifier statux-prod-rds \
--db-snapshot-identifier manual-pre-rollback-$(date +%Y%m%d%H%M)
# 2. Revert the migration (Divinux is the only app with TypeORM migrations;
# Platform applies idempotent DDL on boot)
cd statux-api
npm run migration:revert:divinux
# 3. Verify the database state
psql -h <rds-endpoint> -U statux_admin -d statux -c \
"SELECT * FROM <schema>.migrations ORDER BY id DESC LIMIT 5;"
Database Restore from Snapshot
For severe database issues, restore from the latest automated or manual snapshot:
# List available snapshots
aws rds describe-db-snapshots \
--db-instance-identifier statux-prod-rds \
--query 'sort_by(DBSnapshots, &SnapshotCreateTime)[-5:].[DBSnapshotIdentifier,SnapshotCreateTime,Status]' \
--output table
See the Database Restore runbook for the full restore procedure.
Step 4: Communication
Internal Communication
- Post in
#incidentsSlack channel with severity, affected service, and current status - Tag the on-call engineer and team lead
- Update every 15 minutes for P1, every 30 minutes for P2
Status Page Updates
Use these templates for public status page updates:
Investigating
[Service Name] - Investigating Issues
We are currently investigating reports of [brief description of symptoms]. Our team is actively working to identify the root cause. We will provide an update within [15/30] minutes.
Identified
[Service Name] - Issue Identified
We have identified the cause of [brief description]. [Brief explanation of root cause]. Our team is implementing a fix. We expect resolution within [estimated time].
Monitoring
[Service Name] - Fix Deployed, Monitoring
A fix has been deployed for [brief description]. We are monitoring the system to confirm the issue is fully resolved. We will provide a final update once we are confident in the resolution.
Resolved
[Service Name] - Resolved
The issue affecting [brief description] has been resolved. [Brief explanation of what happened and what was done]. Total duration: [X hours Y minutes]. We apologize for any inconvenience and will be conducting a post-mortem to prevent recurrence.
Step 5: Post-Mortem
After the incident is resolved, create a post-mortem document within 48 hours:
- Timeline: Detailed chronological events
- Root cause: Technical explanation of what went wrong
- Impact: Number of affected users, duration, data impact
- Detection: How was the incident detected? Could we have detected it sooner?
- Response: What worked well? What could be improved?
- Action items: Concrete tasks to prevent recurrence, each with an owner and due date
Use the Divinux RCA feature to create and track post-mortem documents with linked incidents and action items.