Incident response
A calm, ordered way to handle a live incident — severity levels, the first five minutes, runbooks for the common failures, and how to restart what stopped.
Incident response
Something is wrong on a live install: pages 500, leads stopped, payments are not flowing, the queue is backed up. This page is the calm version of those moments. Read the severity table, do the first five minutes, then jump to the matching runbook. Everything here uses tools that already exist in the app — no improvisation required.
Who this is for
- Super admins and developers handling a live incident.
- Whoever is on call when the support ticket lands.
Difficulty: Medium · Time: 20 minutes to read; runbooks are minutes each · Prerequisites: Super Admin access, shell/hosting access, and a way to reach the workspace owner.
Step 0 — Set the severity
| Severity | Examples | Response |
|---|---|---|
| SEV1 | App down for everyone; data loss suspected; payment webhooks failing across tenants | Drop everything; work it live; communicate |
| SEV2 | Leads stopped for one workspace; WhatsApp messages failing; login broken for a team | Fix within hours; keep the affected owner updated |
| SEV3 | One user cannot log in; one report looks wrong | Normal ticket flow; see Troubleshooting |
The first five minutes (any severity)
- Confirm what users see — open
GET {app URL}/api/v1/healthand the login page. Degraded or 503 tells you it is infrastructure; 200 tells you it is application logic. - Look at the log — tail
storage/logs/laravel.log. The newest ERROR lines usually name the exact class or integration. Keep the lines; they are evidence. - Check the boring things — disk space (System Health shows total/free/used), database reachable (
php artisan db:show), and whether a deployment or update happened recently (Super Admin → Settings → Updates). - Check the queue —
php artisan queue:failed; is the worker running; is the driversyncwhen it should not be? - Write down the timeline — when it started, what you tried, what changed. You will need it for the post-incident note, and it stops you retrying the same fix.
Runbook — the app is down or 500s
- Put the site into maintenance mode while you work:
php artisan down(this shows a clean maintenance page instead of stack traces). - Re-read the newest errors in
storage/logs/laravel.log. If they mention config/view/route caches built under a different environment, open System Health and use Clear caches (optimize:clear), then Rebuild caches only after the app is healthy. - If a deployment just happened: run Run migrations on System Health (
migrate --force), confirmphp artisan migrate:statusis clean, and if the upgrade is broken, roll back by restoring the pre-update backup (see the backups runbook below). Deployment specifics live in Deployment & server errors. - If complaints mention missing images/uploads: Storage link on System Health (
storage:link). - When healthy:
php artisan up, then confirm health endpoint ok and a login works before telling anyone it is fixed.
Runbook — queue and scheduler stopped
Symptoms: notifications late, WhatsApp not sending, digests missing, queue_failures climbing, jobs in failed_jobs.
- Restart the worker — System Health → Restart queue (
queue:restart; when the driver issyncthe page warns you that this does not apply — fix the driver first). - Start the worker properly on the server:
php artisan queue:work --queue=default,webhooks,automations,integrations,notifications,exports,ai-sdr,mailAll queues must be listed; a missing one silently starves that feature. - Read the failed jobs (
php artisan queue:failed) and map the exception to a troubleshooting page before retrying. What failed once will fail again unchanged. - Scheduler: on shared hosting make sure the single
cron.phpentry point is still being called every minute (it drains the queue with a time budget, then runs the scheduler). On a VPS, confirm theschedule:runcron line. Look forschedule task failed:lines in the log.
Runbook — leads stopped arriving
Follow the decision path in Leads not entering the CRM. The short version: connection health → page token → form allowlist → webhook logs → permissions → test lead → assignment. Check Webhook Logs before touching anything — it tells you whether Meta is reaching you at all.
Runbook — payments failing or billing drift
- Super Admin → Billing → Commercial → Payments (
/super-admin/billing/commercial-payments): what is the provider actually saying? - Read any open reconciliation alert on the billing overview — a
BillingReconciliationAlertmeans the provider status and the CRM disagree; resolve the alert deliberately rather than assuming. - Check the provider configuration: Commercial Providers (
/super-admin/billing/commercial-providers) — environment (sandboxvsproduction), keys, and the webhook secret. A sandbox/production mix-up is the classic cause. - Confirm webhooks are arriving: the endpoints are
POST /api/webhooks/razorpayandPOST /api/webhooks/cashfree; duplicates are ignored safely (idempotent processing), signature mismatches are rejected. - Full detail and per-symptom fixes: Payments failing.
Runbook — backups and restore
- Super Admin → Settings → Backups (
/super-admin/settings/backups): check the newest backup exists and Verify it (health + SQL statement count). - Restore: use the row's Restore action — it extracts the zip and imports the SQL, then reports files restored and rows imported. Do this on a test copy first when the production wipe is not the safer option.
- If the situation is a bad update: the updater took a pre-update backup automatically — restore exactly that one.
- After any restore, re-check the health endpoint, log a login test, and re-run a queue restart.
Runbook — suspected data exposure or abuse
- Rotate secrets: Meta App Secret, payment provider keys/webhook secrets, SMTP password, WhatsApp tokens,
CRON_SECRET. Assume anything readable is burned. - Review the audit trail: admin actions and sensitive changes are recorded in the audit log (retained 180 days by default). The tenant's Data & Privacy page (
/admin/privacy) is where exports and deletion requests live; do not delete anything while an incident is open. - Limit blast radius: disable a compromised integration connection, revoke affected users, and check Super Admin → Android App → Devices for unexpected device registrations.
- Escalate — treat this as SEV1 and involve the platform owner before communicating.
Communicating during an incident
- One channel, one person speaking: name an incident lead even if it is just you.
- Short updates, timestamped: what is affected, what we are doing, when the next update comes. Do not promise a root cause you do not have.
- When resolved: say what was fixed and what users need to do (usually only "reload" or "log in again").
After it is fixed (post-incident)
- Re-check the health endpoint and the specific thing that broke (a real lead through Meta, a real WhatsApp message, a real payment).
- Write down: timeline, root cause, what fixed it, and the check that would have caught it earlier.
- Add that check to Daily checks or Monitoring & alerts so the next occurrence is a non-event.
Common mistakes
| Mistake | Why it hurts | Do this instead |
|---|---|---|
| Fixing before reading the log | You change state and destroy the evidence | Tail the log first, always |
| Clearing caches on a hunch during SEV1 | Rebuilds can take the site down longer | Only after you have read the error |
| Retrying failed jobs blindly | The same failure repeats and hides the real error | Read the exception, fix the cause, then retry |
| Restoring a backup onto production without verifying | You can turn a partial outage into a full one | Verify, test-restore, then restore deliberately |
Forgetting to run php artisan up |
You sit at a working site nobody can reach | Make "up" part of the fix checklist |
Technical details
- Maintenance mode:
php artisan down/php artisan up. - System Health actions: Clear caches (
optimize:clear), Run migrations (migrate --force), Rebuild caches, Storage link (storage:link), Restart queue (queue:restart) —/super-admin/settings/system-health. - Backups:
leadhub:backup(nightly, if enabled), Backups page for Verify/Restore/Download/Delete;BackupService::restorereports files restored and rows imported. - Suspension vs outage: a suspended workspace redirects to
/admin/subscription-required(not an outage) — see Payments failing.
Related guides
Was this page helpful?
Thanks — noted. ✦