Incident Response #
This runbook covers the technical side of production incidents: investigation, mitigation and recovery. For paging, declaring, roles and postmortems, see Incident Management.
When to Use This Runbook #
- Production service outage or degradation
- Security incidents or suspected breaches
- Data integrity issues
- Customer-impacting bugs
- System performance degradation
- Third-party service failures affecting BonsAI
- Datadog On-Call page received
Incident Severity Levels #
Use the SEV-1 to SEV-3 scale in Managing Incidents. It is the only severity scale.
Incident Response Phases #
Phase 1: Detection & Triage (0-5 minutes) #
Goal: Identify and assess the incident quickly
Step 1: Alert Received #
Incidents may be detected through:
- Datadog On-Call - Primary paging system (
@oncall-<team>) - Monitoring alerts (Datadog, CloudWatch)
- Customer reports (support tickets, Slack)
- Error tracking (Sentry)
- Team member observation
Datadog On-Call:
- Acknowledge the page within 10 minutes
- Declare an incident in Datadog if impact is real
- Join the auto-created incident Slack channel
See On-Call and Triggering Incidents.
Step 2: Initial Assessment #
Quick questions to answer:
1. What is broken? (service, feature, user flow)
2. How many users are affected? (all, some, specific segment)
3. Is this a new issue or recurring?
4. When did it start? (use monitoring dashboards)
5. What changed recently? (deployments, config changes)
Gather initial evidence:
# Check service health
kubectl get pods
kubectl get pods --all-namespaces | grep -v Running
# Check recent deployments
kubectl rollout history deployment/bonsapi-deployment
# Check recent events
kubectl get events --sort-by='.lastTimestamp' | head -20
# Check error rates in Datadog
# Check Sentry for exception spikes
Step 3: Determine Severity #
Use the severity levels to classify the incident.
Severity Decision Tree:
Is production completely down? → SEV-1
Is a critical user flow broken? → SEV-2
Is a feature broken with no workaround? → SEV-3
Is there a workaround or is it cosmetic? → Linear ticket, no incident
Phase 2: Response & Mitigation (5-30 minutes) #
Goal: Stop the bleeding, restore service
Step 1: Communicate #
Follow Managing Incidents for declaring, the incident channel, status templates and stakeholder updates.
Step 2: Confirm Roles #
Roles are fixed; do not assign an IC. See Managing Incidents.
- Incident Commander (IC) - Ken Kanai, always
- Lead Responder - First to acknowledge from the owning team
- Responder(s) - Owning team on-call, plus teams pulled in
- Admin team - Oversight and cross-team coordination
- Communications - Assigned by the IC for customer-facing incidents
Step 3: Investigate #
Use the appropriate runbook:
| Symptom | Runbook |
|---|---|
| API errors/downtime | Monitoring & Alerting |
| Pods crashing | Kubernetes Debugging |
| Database issues | Database Access |
| Queue backlog | RabbitMQ Management |
| Deployment issues | Deployment Monitoring |
Investigation checklist:
# 1. Check service status
kubectl get pods -o wide
kubectl get services
kubectl get ingress
# 2. Check pod logs
kubectl logs -l app=bonsapi --tail=100
kubectl logs -l app=bonsapi --tail=100 | grep -i error
# 3. Check events
kubectl get events --sort-by='.lastTimestamp' | head -30
# 4. Check resource usage
kubectl top nodes
kubectl top pods
# 5. Check external dependencies
# - Database connectivity
# - Redis connectivity
# - RabbitMQ status
# - Third-party APIs (Clerk, Stripe, etc.)
# 6. Review recent changes
git log --oneline --since="2 hours ago"
# Check GitHub Actions for recent deployments
Step 4: Implement Mitigation #
Mitigation strategies (in order of preference):
-
Quick fix (if root cause is known and simple)
# Example: Fix config issue kubectl edit configmap app-config kubectl rollout restart deployment/bonsapi-deployment -
Rollback (if caused by recent deployment)
kubectl rollout undo deployment/bonsapi-deployment kubectl rollout status deployment/bonsapi-deployment -
Scale up (if resource exhaustion)
kubectl scale deployment/bonsapi-deployment --replicas=5 -
Disable feature (if feature causing issues)
# Use feature flag to disable problematic feature # Update in Doppler or config -
Failover (if infrastructure issue)
- Route traffic to backup region (if available)
- Switch to backup database
- Use cached data
Step 5: Verify Mitigation #
After implementing mitigation:
# 1. Check service health
kubectl get pods
kubectl logs <pod-name> --tail=50
# 2. Test affected functionality
curl https://api.gotofu.com/health
# Test specific endpoints that were broken
# 3. Monitor metrics
# - Error rate should drop to normal
# - Response time should improve
# - Request volume should recover
Update stakeholders:
✅ MITIGATION APPLIED
Action: Rolled back to previous version
Status: Service restored
Impact: API errors stopped, service operational
Time to mitigate: 18 minutes
Next steps: Root cause analysis
Update Datadog:
- Add the mitigation to the incident timeline
- Move the incident to Stable (not “Resolved” yet)
Phase 3: Resolution & Recovery (30+ minutes) #
Goal: Fully resolve the issue and restore normal operations
Step 1: Confirm Full Recovery #
- All metrics back to baseline
- Error rates normal
- No customer complaints
- All dependent systems operational
Step 2: Identify Root Cause #
5 Whys Analysis:
Example:
Problem: API returned 502 errors
Why? → BonsAPI pods were not responding
Why? → Pods were out of memory (OOMKilled)
Why? → Memory leak in new code
Why? → Missing memory cleanup in document processing
Why? → Code review didn't catch the leak
Root Cause: Insufficient testing and code review for memory management
Step 3: Implement Permanent Fix #
-
Create fix branch
git checkout -b fix/incident-api-oom -
Implement fix
- Fix the root cause
- Add tests to prevent regression
- Update documentation
-
Test thoroughly
mise run test mise run ci -
Deploy fix
- Follow standard deployment process
- Monitor closely during rollout
Step 4: Communicate Resolution #
🎉 INCIDENT RESOLVED
Issue: Memory leak in document processing
Root Cause: Missing cleanup in new feature
Fix: Deployed patch v2.1.3
Status: Fully resolved
Duration: 45 minutes
Customer impact: 50% of API requests affected
Follow-up: Post-incident review scheduled
Close the Datadog Incident:
- Add a final resolution note to the timeline
- Move the incident to Resolved
- Generate the postmortem (see Postmortems)
Phase 4: Post-Incident Review #
Follow Postmortems. Deadlines, template and approval depend on severity.
Common Incident Scenarios #
Scenario 1: Complete Service Outage #
Symptoms:
- All API requests failing
- Health checks failing
- Pods not responding
Quick Actions:
# 1. Check pod status
kubectl get pods -o wide
# 2. Check recent deployments
kubectl rollout history deployment/bonsapi-deployment
# 3. Rollback immediately
kubectl rollout undo deployment/bonsapi-deployment
# 4. Monitor recovery
kubectl rollout status deployment/bonsapi-deployment
Scenario 2: Database Connection Issues #
Symptoms:
- Database connection errors in logs
- Timeouts on database queries
- 500 errors from API
Quick Actions:
# 1. Check YugabyteDB cluster health in the YugabyteDB console
# 2. Test connectivity from pod
kubectl exec -it <pod-name> -- nc -zv <db-host> <db-port>
# 3. Check connection pool
kubectl logs -l app=bonsapi | grep "connection pool"
# 4. Scale down if overwhelming DB
kubectl scale deployment/bonsapi-deployment --replicas=2
Scenario 3: Third-Party Service Failure #
Symptoms:
- Errors calling external API (Clerk, Stripe, etc.)
- Timeouts on authentication/payments
- Partial functionality broken
Quick Actions:
-
Verify third-party status
- Check status page (status.clerk.com, status.stripe.com)
- Test API directly
-
Enable graceful degradation
- Use cached data if available
- Queue requests for retry
- Show user-friendly error message
-
Communicate with users
- Status page update
- In-app notification
Scenario 4: Security Incident #
Symptoms:
- Suspicious activity in logs
- Unexpected data access
- Security alert from monitoring
CRITICAL ACTIONS:
-
Contain the threat IMMEDIATELY
# Isolate affected systems kubectl scale deployment/<affected-deployment> --replicas=0 # Rotate potentially compromised credentials # See Secrets Management runbook -
Preserve evidence
- Capture logs
- Take snapshots
- Document findings
-
Escalate to security team
- DO NOT discuss in public channels
- Use secure communication
-
Follow security incident protocol
- Assess scope of breach
- Notify affected parties (if required)
- Comply with legal/regulatory requirements
Incident Communication #
Internal Communication #
Status updates every 15-30 minutes:
⏱️ STATUS UPDATE (10:30 UTC)
Current status: Still investigating
Progress: Identified high memory usage in API pods
Next steps: Implementing memory limit increase as temporary fix
ETA: 10 minutes
Customer Communication #
For customer-facing incidents:
-
Initial acknowledgment (< 15 minutes)
We're aware of an issue affecting API response times. Our team is investigating and will provide updates soon. -
Status updates (every 30-60 minutes)
Update: We've identified the cause and are implementing a fix. Impact: ~50% of API requests experiencing delays. ETA: Service restoration expected within 30 minutes. -
Resolution notice
Resolved: The API issue has been fixed and service is fully restored. We apologize for the inconvenience and are taking steps to prevent recurrence.
Incident Tools & Resources #
Quick Access Links #
- GitHub Repository: https://github.com/tofu2-limited/bonsai
- GitHub Actions: https://github.com/tofu2-limited/bonsai/actions
- Datadog Dashboard: https://app.datadoghq.com
- AWS Console: https://console.aws.amazon.com
- Linear: https://linear.app
Useful Commands #
# Quick health check script
kubectl get pods -o wide && \
kubectl get deployments && \
kubectl get services && \
kubectl top nodes && \
kubectl top pods
# Tail logs from all services
kubectl logs -f -l app=bonsapi &
kubectl logs -f -l app=webapp &
kubectl logs -f -l app=bonsai-invoice &
# Watch events
watch kubectl get events --sort-by='.lastTimestamp'
Escalation Path #
When to Escalate #
- Incident severity is SEV-1
- Mitigation attempts have failed
- Issue requires specialized expertise
- Legal or compliance concerns
- Security incident
Escalation Contacts #
Follow Managing Incidents.
- Owning team (
@oncall-<team>)- Paged automatically by the escalation policy
- Another team (
@oncall-ai,@oncall-frontend,@oncall-backend,@oncall-infra)- Page their handle from the incident channel when you need their expertise
- Admin team (
@oncall-admin)- Cross-team coordination and severity review
- Ken Kanai (Incident Commander)
- Every decision and every change to the incident
- Security, legal and compliance concerns
- Assigns Communications for customer-facing updates
Best Practices #
During Incidents #
- Stay calm - Clear thinking is crucial
- Communicate clearly - Avoid jargon, be specific
- Document everything - Actions, findings, decisions
- Focus on mitigation first - Root cause analysis comes later
- Don’t guess - Verify before implementing changes
- Ask for help - Escalate early if stuck
Incident Prevention #
- Monitor proactively - Don’t wait for customers to report
- Test thoroughly - Catch issues before production
- Deploy carefully - Use canary/blue-green deployments
- Review regularly - Learn from past incidents
- Practice - Run incident response drills
Post-Incident #
- Close the loop - Complete all action items
- Share learnings - Educate the team
- Update runbooks - Improve documentation
- Recognize effort - Thank the responders
See Also #
- Incident Management - Paging, lifecycle and postmortems
- Monitoring & Alerting - Detection and alerting
- Kubernetes Debugging - Pod troubleshooting
- Database Access - Database incidents
- RabbitMQ Management - Queue incidents
- Deployment Monitoring - Deployment issues
- Secrets Management - Credential rotation