Purpose: Production-ready incident triage runbook for on-call engineers. Audience: All on-call engineers (first responder). Owner: DevOps / Platform Team Last Updated: July 29, 2026 Related: Runbooks Overview · Quick Reference · Escalation Matrix · Incident Response (RPC/Delivery) · Postmortem Playbook · Triage Rotation Calendar
Classify every incident into one of four severity levels. When in doubt, round up — it is safer to downgrade later than to under-escalate a critical incident.
| Criteria | Example Scenarios |
|---|---|
| Complete platform outage | All API routes returning 5xx; frontend unreachable |
| Funds at risk | Withdrawals debited on-chain but not received; unauthorized contract interaction |
| Data loss / corruption | Database unrecoverable; audit log gap exceeding 15-minute RPO |
| Active security breach | Key compromise; exploit in progress; unauthorized admin access |
| RPO exceeded | Data loss beyond the 15-minute Recovery Point Objective |
Response SLA: Acknowledge within 5 minutes. Mitigation target: immediate, all hands.
Ownership & Escalation:
- First responder acknowledges and pages Incident Commander + Security on-call immediately.
- War room created (
#yieldvault-war-room). - Domain SMEs (Contracts, Backend) paged.
- Stakeholders notified via status page within 15 minutes.
- Post-mortem required within 48 hours.
| Criteria | Example Scenarios |
|---|---|
| Core feature unavailable | Deposits failing for all users; vault page not loading |
| Circuit breaker open | Soroban write path shedding load; 503s on critical endpoints |
| Widespread partial failure | > 20% of requests failing on a critical path |
| Degraded performance | P95 latency > 5× baseline for > 10 minutes |
| RPC provider outage | Primary RPC unresponsive; failover required |
Response SLA: Acknowledge within 15 minutes. Mitigation target: 30–60 minutes.
Ownership & Escalation:
- First responder acknowledges and pages Incident Commander.
- Domain SMEs notified.
- Status page update within 30 minutes.
- Escalate to Sev0 if not mitigated within RTO (60 minutes).
| Criteria | Example Scenarios |
|---|---|
| Non-critical feature broken | Portfolio history not loading; referral page error |
| Limited user scope | Single wallet or small subset affected |
| Workaround exists | Users can still perform core actions via alternate path |
| Non-production affected | Staging/testnet environment issues |
| Scheduled maintenance | Planned downtime communicated in advance |
Response SLA: Acknowledge within 1 hour. Mitigation target: next business day.
Ownership & Escalation:
- First responder may own; IC optional.
- File a tracking issue; no war room required unless it escalates.
- Escalate to Sev1 if scope widens or unresolved after 4 business hours.
| Criteria | Example Scenarios |
|---|---|
| Cosmetic / UI glitch | Visual layout issue; non-blocking console warning |
| Documentation gap | Outdated runbook step; missing error code entry |
| Flaky test | Intermittent CI failure with no production impact |
| Future risk | Deprecation warning; dependency EOL 6+ months out |
Response SLA: Acknowledge within 1 business day. Mitigation target: current sprint or backlog.
Ownership & Escalation:
- File a GitHub issue with
priority: low. - No immediate action required; address in backlog grooming.
- Escalate only if impact grows.
- Monitoring alerts — PagerDuty, Grafana, Prometheus (see Monitoring & Observability)
- User reports — Support tickets, social media, in-app feedback
- Health check failures — CI/CD pipeline or cron job detects degradation
- Manual discovery — On-call engineer notices anomalous metrics during routine review
- Security scanning alerts —
secret-scanning.yml,slither.yml,rust-security.yml
- Acknowledge the PagerDuty alert or Slack notification.
- Post in
#yieldvault-incidents:🚨 ACKNOWLEDGED: [Alert name] Investigating — will update within 15 min.
- Check dashboards. Open Grafana and confirm the alerting metric is anomalous.
- Run health checks:
curl -s http://localhost:3000/health | jq . curl -s $STELLAR_RPC_URL -X POST \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"getHealth"}' | jq .
- Spot-check logs for correlated errors around the alert time:
journalctl -u yieldvault-backend --since "15 min ago" | grep -i "error\|fatal"
- If false alarm: Post
✅ False alarm: [brief reason]and close. File a ticket if the alert threshold needs tuning.
| Question | How to Answer |
|---|---|
| What components are affected? | Check health endpoints for backend, DB, RPC, frontend. |
| Who is affected? | All users, a region, a single wallet? Query logs for unique affected addresses. |
| When did it start? | Correlate with deploy times, config changes, or external events. |
| Is it getting worse? | Check metric slope — flat, increasing, or recovering? |
Apply the severity criteria from §1. Be decisive — classify within 2 minutes and revise later if needed.
Decision shortcut: If you hesitate between two levels, pick the higher one. Downgrading is a Slack message; upgrading is a page.
| Severity | Action |
|---|---|
| Sev0 | Page IC + domain SME + Security immediately. Start incident report. |
| Sev1 | Page IC. Notify domain SMEs. Start incident report. |
| Sev2 | Own it. File tracking issue. Notify team lead if not resolved within 1 hour. |
| Sev3 | File a GitHub issue. No further immediate action. |
Use the quick-reference in §6 to jump to the appropriate domain playbook.
- Acknowledge the alert (PagerDuty / Slack).
- Post initial notification in
#yieldvault-incidents. - Validate the signal is not a false alarm.
- Determine scope (components, users, geography).
- Classify severity (Sev0–Sev3).
- Escalate per severity guidelines.
- Create incident channel / war room if Sev0 or Sev1.
- Engage the appropriate domain playbook.
- Execute mitigation steps.
- Provide status updates (every 15 min for Sev0, 30 min for Sev1).
- Verify mitigation is working.
- Update status page (if Sev0/Sev1).
- Start incident report document.
- Verify all metrics returned to baseline for at least 5 minutes.
- Run smoke-test suite:
cd contracts && cargo test --workspace --quiet cd ../backend && npm test cd ../frontend && npm run test:run
- Re-enable any disabled services / circuit breakers.
- Monitor for residual errors for 30 minutes.
- Document the incident timeline, root cause, and actions taken.
- Schedule post-mortem (within 48 hours for Sev0/Sev1).
| Condition | Action |
|---|---|
| Sev0 declared | Page IC + Security on-call immediately. |
| Sev1 not mitigated within 60 minutes | Escalate to Sev0; page IC if not already engaged. |
| Sev2 unresolved after 4 business hours | Notify team lead; escalate to Sev1 if scope widens. |
| Suspected contract / fund-safety issue | Page Contracts SME + IC regardless of severity. |
| Security scanning alert (High/Critical) | Follow Security Scanning Guide; page Security on-call. |
| Role | Channel / Contact |
|---|---|
| Incident Commander | PagerDuty: "YieldVault IC" |
| Backend on-call | #backend-oncall |
| Contracts on-call | #contracts-oncall |
| Frontend on-call | #frontend-oncall |
| Platform / Infra | #platform-oncall |
| Security on-call | PagerDuty: "YieldVault Security" |
Full rotation schedule in Triage Rotation Calendar.
- Do keep all incident-related discussion in the designated channel.
- Do prefix messages with relevant labels (
[Triage],[Action],[Question]). - Do post links to dashboards, logs, and runbooks.
- Don't speculate on root cause in customer-facing status updates.
- Don't make unilateral changes without posting in the channel first.
| Severity | Update Frequency | Audience | Channel |
|---|---|---|---|
| Sev0 | Every 15 minutes | All stakeholders | War room + status page |
| Sev1 | Every 30 minutes | Engineering + Product | Incident channel + status page |
| Sev2 | Every 1–2 hours | Engineering team | Incident channel |
| Sev3 | No cadence | Issue tracker | GitHub issue |
Initial Acknowledgment (T+0–5):
🚨 INCIDENT: [Brief one-liner]
Severity: [Investigating / Sev0 / Sev1 / Sev2]
Scope: [What's affected, how many users]
IC: [Name or "TBD"]
Channel: #yieldvault-war-room
Next update: [Time, within 15–30 min]
Status Update:
📊 UPDATE: [Incident name]
Severity: [Unchanged / Upgraded to SevX]
Progress: [Current action, blockers]
Mitigation ETA: [Time or "TBD"]
Next update: [Time]
Mitigated:
🔧 MITIGATED: [Incident name]
Action taken: [Brief description]
Monitoring: [Metrics being watched]
Canary status: [Passed / In progress]
Next: Verification + postmortem
Resolved:
✅ RESOLVED: [Incident name]
Duration: [Start → End UTC]
Severity: [Final]
Impact: [Users affected, data loss if any]
Root cause (initial): [One line]
Postmortem: [Ticket/PR link or "TBD within 48h"]
Status Page (Customer-Facing):
- Investigating: "We are investigating reports of [symptom]. Some users may experience [impact]. Funds remain secure. Next update in 30 minutes."
- Identified: "We have identified the cause as [brief]. Our team is working on a fix."
- Monitoring: "A fix has been deployed. We are monitoring closely to confirm resolution."
- Resolved: "This incident has been resolved. A full postmortem will be published within 5 business days."
| Symptom | Default Severity | Playbook |
|---|---|---|
| All endpoints returning 5xx | Sev0 | Backend Redeploy |
| Database unreachable or corrupted | Sev0 | Database Restore |
| Funds at risk / unauthorized on-chain activity | Sev0 | Contract Upgrade Playbook |
| Active security breach | Sev0 | Full DR Procedure + Security |
| Primary RPC unresponsive / high latency | Sev1 | RPC Failover |
| Withdrawals failing (funds not debited) | Sev1 | Failed Withdrawal Playbook |
| Withdrawals debited on-chain, not received | Sev0 | Failed Withdrawal Playbook + escalate immediately |
| Transaction delivery failures spiking | Sev1 | Incident Response Runbook |
Specific error code (SOROBAN_*, VAULT_*) |
Sev1/Sev2 | Error Code Troubleshooting |
| Ledger event gap / email queue stuck | Sev2 | Replay & State Recovery |
| Contract upgrade failure / rollback needed | Sev0 | Contract Upgrade Playbook |
| Complete infrastructure loss | Sev0 | Full DR Procedure |
| CI/CD pipeline failure (non-production) | Sev2 | File issue; notify #platform-oncall |
| Security scanning alert (High/Critical) | Sev0/Sev1 | Security Scanning Guide |
| Rate limiting / abuse pattern | Sev1 | Check rateLimiter.ts; page Backend on-call |
- Validate the final severity classification — did it match impact?
- Ensure an incident report was filed and a post-mortem is scheduled (Sev0/Sev1).
- Review alert thresholds that triggered false positives and file tuning tickets.
- If this runbook was unclear or missing a path, update it in the same PR as post-mortem action items.
- Confirm the incident is linked in
docs/incidents/README.md.
Before your first on-call shift, confirm:
- You can access Grafana, PagerDuty, and the deployment dashboard.
- You have SSH /
kubectl/ cloud console access to production. - You can run health checks:
curl -s http://localhost:3000/health | jq . psql $DATABASE_URL -c "SELECT 1" curl -s $STELLAR_RPC_URL -X POST \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"getHealth"}' | jq .
- You know where backups are stored:
s3://yieldvault-backups/database/ - You have read and understood this runbook and know the difference between Sev0, Sev1, Sev2, and Sev3.
Last Updated: July 29, 2026 Maintained By: DevOps / Platform Team Next Review: October 29, 2026