Operations Runbook
Incident response and maintenance
This runbook is for engineers and on-call operators handling production issues for
Girard AI. The canonical deployment path is Coolify building the Dockerfile
from the live branch. For setup details, see the
Coolify deployment guide.
First Response Checklist
- Classify the incident:
P0: site unavailable, auth/session failures for most users, data loss, security incident, or payments blocked.P1: major feature unavailable, sustained 5xx rate, failed deploy, or background jobs stopped.P2: degraded performance, isolated route failure, provider outage with a working fallback, or noisy but contained error spike.
- Preserve evidence before changing anything:
- Affected URL, user or organization ID, browser and device, timestamp, and screenshot or response body.
x-correlation-idandx-request-idresponse headers from the failing request.- Current
/api/versionpayload and latest Coolify deployment ID.
- Check the live app:
curl -i "$APP_URL/api/version" curl -i "$APP_URL/api/health" curl -i "$APP_URL/api/health?strict=1" curl -i "$APP_URL/api/ready" - Open Coolify logs for the app container and, when relevant, the worker
container running
npm run worker. - Search Sentry for the route, digest, user ID,
x-correlation-id, orx-request-id. - Decide whether the safest immediate action is rollback, env correction, provider failover, traffic shaping, or a hotfix.
Operational Signals
| Signal | Where to check | Healthy result |
|---|---|---|
| Deploy freshness | GET /api/version | JSON includes the expected commit SHA and app version. |
| Liveness | GET /api/health | 200 with status: "healthy" or status: "degraded" for non-strict dependency warnings. |
| Strict readiness | GET /api/health?strict=1 | 200 only when database and required env checks pass. |
| Runtime readiness | GET /api/ready | 200 with ready: true, database ok, cache ok, and environment ok. |
| Errors | Sentry and Coolify runtime logs | Events contain route/source/runtime tags and correlation IDs when present. |
| Request tracing | Response headers and structured logs | x-correlation-id is stable across retries; x-request-id identifies the specific request. |
| API throttling | Response headers | X-RateLimit-* headers count down before any 429. |
| Web Vitals | Signed-in /performance dashboard | Health score, route hot spots, and recent samples reflect current traffic. |
| Background jobs | Coolify worker logs and Redis | Jobs are being consumed; no repeated BullMQ connection errors. |
Common Incident Playbooks
App returns 5xx
Symptoms: sustained 500 or 503, dashboard crash boundary, Sentry spike, or
Coolify logs showing repeated unhandled exceptions.
- Confirm whether the latest deploy is live:
curl -i "$APP_URL/api/version" - Capture the failing response headers:
curl -i "$APP_URL/path-that-fails" - Use
x-correlation-idandx-request-idto search Coolify logs and Sentry. - Check whether the issue started immediately after the latest Coolify deploy.
- Roll back from the Coolify deployment list if the current deploy introduced the error and the previous image is known good.
- If rollback is not viable, patch the route or boundary and add a focused regression test for the failing payload.
Health or readiness is failing
Symptoms: /api/health?strict=1 or /api/ready returns 503.
- Compare non-strict and strict checks:
curl -i "$APP_URL/api/health" curl -i "$APP_URL/api/health?strict=1" curl -i "$APP_URL/api/ready" - If environment is failing, inspect app runtime logs for
missingKeys. The public response intentionally hides individual secret names. - Validate required configuration locally against
lib/env/contract.ts:npx tsx scripts/validate-env.ts - Check these required production values first:
DATABASE_URLJWT_SECRETENCRYPTION_KEYNEXT_PUBLIC_APP_URLNEXT_PUBLIC_MARKETING_URL- At least one of
OPENAI_API_KEY,ANTHROPIC_API_KEY, orGOOGLE_GENERATIVE_AI_API_KEY
- If database is failing, confirm the Coolify Postgres resource is running,
DATABASE_URLpoints at the reachable internal host, and migrations have been applied with:npx prisma migrate deploy - If cache is failing in
/api/ready, checkENABLE_REDIS_CACHE,CACHE_REDIS_URL, andREDIS_URL. Single-node fallback should still work when Redis cache is disabled.
API requests are rate limited
Symptoms: API responses return 429 with RATE_LIMITED and Retry-After.
- Capture the rate-limit headers:
curl -i "$APP_URL/api/some-route" - Confirm whether broad API rate limiting is enabled:
ENABLE_API_RATE_LIMITINGorAPI_RATE_LIMIT_ENABLEDAPI_RATE_LIMIT_MAX_REQUESTSAPI_RATE_LIMIT_WINDOW_MSAPI_RATE_LIMIT_BYPASS_PATHS
- Default bypass paths are
/api/health,/api/ready, and/api/admin/health. - If a proxy is collapsing many users into one IP, verify Coolify forwards
x-forwarded-for,x-real-ip, orcf-connecting-ip. - For an incident mitigation, raise the limit or add a narrow bypass path. Keep product-level upload, chat, and generation limits in place.
Sentry is not receiving errors
Symptoms: users see an error boundary, but no Sentry event appears.
- Verify runtime DSNs:
- Server and edge:
SENTRY_DSN - Browser:
NEXT_PUBLIC_SENTRY_DSN
- Server and edge:
- Verify enable flags and metadata:
SENTRY_ENABLEDNEXT_PUBLIC_SENTRY_ENABLEDSENTRY_ENVIRONMENTorNEXT_PUBLIC_SENTRY_ENVIRONMENTSENTRY_RELEASEorNEXT_PUBLIC_SENTRY_RELEASESENTRY_TRACES_SAMPLE_RATEorNEXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATE
- Check the route, digest, source, runtime, and correlation tags on captured events.
- If errors are ignored, compare the message to the shared ignore lists in
lib/error-tracking.ts. - If source maps are needed for a release, confirm the build plugin is enabled in the deployment environment before the next build.
Performance is degraded
Symptoms: users report slow pages, poor interaction latency, or the performance dashboard shows poor LCP, INP, CLS, FCP, or TTFB.
- Open the signed-in
/performancedashboard. - Check the health score, worst metric, route hot spots, sample count, and recent measurements.
- Fetch the aggregated Web Vitals payload when debugging authenticated traffic:
curl -i "$APP_URL/api/performance/vitals" - If samples are empty, confirm the browser is loading the Web Vitals reporter
and that the page can POST beacons to
/api/performance/vitals. - For poor LCP or TTFB, inspect database queries, external provider calls, and server logs for the same route and correlation ID.
- For poor INP, reproduce in the browser, profile the interaction, and check whether a client component is doing heavy synchronous work.
Deploy fails or build OOMs
Symptoms: Coolify build fails, the image does not start, or logs mention memory pressure.
- Confirm Coolify is building from
deploy/coolify-live; stale branches are a common cause of "deploy succeeded but nothing changed". - Check build variables:
NEXT_BUILD_MAX_OLD_SPACE_SIZENEXT_BUILD_CPUSNEXT_STATIC_GENERATION_MAX_CONCURRENCY
- The Next build intentionally skips its internal type checker because this repository type-checks separately. Do not re-enable build-time type errors as part of incident response.
- If memory is tight, lower build parallelism before retrying:
NEXT_BUILD_CPUS=1 NEXT_STATIC_GENERATION_MAX_CONCURRENCY=1 npm run build - Reproduce locally with focused verification first, then
npm run buildif memory allows. - If the container starts but fails immediately, check that
npm run startpasses env validation before launching.next/standalone/server.js.
Background jobs are stalled
Symptoms: async work queues up, generated assets do not finish, webhook follow-up jobs do not run, or worker logs are quiet.
- Confirm the separate Coolify worker application is running with start command
npm run worker. - Confirm both app and worker share:
ENABLE_BACKGROUND_QUEUE=trueREDIS_URL- Any provider or storage env vars used by the job family.
- Check worker logs for BullMQ connection errors, repeated job failures, or missing env validation.
- Tune
QUEUE_WORKER_CONCURRENCYonly after confirming Redis and provider dependencies are healthy. - If Redis is unavailable, web requests continue, but queue producers no-op with warnings until Redis is restored.
AI provider or image generation outage
Symptoms: chat, agent, Studio, image, video, audio, or speech generation fails.
- Identify the provider family from the failing route, model, or product area.
- Check provider status and recent Coolify logs.
- Confirm at least one core AI provider key is configured for health:
OPENAI_API_KEY,ANTHROPIC_API_KEY, orGOOGLE_GENERATIVE_AI_API_KEY. - For Studio image generation, confirm the model-specific keys:
FAL_KEYfor Flux and Stable Diffusion models.OPENAI_API_KEYfor DALL-E and GPT Image models.GOOGLE_GENERATIVE_AI_API_KEYfor Imagen and Gemini image models.
- Temporarily hide or disable the affected provider family if fallback quality is better than repeated user-visible failures.
Cache, trending, or hot-path data looks stale
Symptoms: hot-path API responses do not update, route dashboards disagree with recent writes, or Studio trending data appears stale.
- Check whether distributed cache is enabled:
ENABLE_REDIS_CACHECACHE_REDIS_URLorREDIS_URL
- Inspect response cache headers such as
X-API-Cacheon affected API routes. - Confirm the cache backend in
/api/readydiagnostics. - If a hot path is stale after a deploy, disable Redis cache temporarily or clear the relevant Redis keys from the Coolify Redis console.
- Keep local in-memory fallback enabled for single-node recovery.
Rollback Procedure
- Prefer Coolify's deployment rollback for a bad release. It restores the previous image faster than a revert build.
- Confirm the rollback version:
curl -i "$APP_URL/api/version" curl -i "$APP_URL/api/health?strict=1" - If the issue was caused by a database migration, do not roll back code until the schema compatibility risk is understood.
- After service recovery, create a follow-up fix or revert commit on
deploy/coolify-live. - Record the incident summary, root cause, mitigation, affected users, and follow-up tasks.
Escalation Criteria
Escalate to the engineering lead immediately for P0 incidents, suspected security or data exposure, destructive migration risk, payment disruption, or any rollback that might conflict with database state. Escalate to provider support when the app checks are healthy but the upstream provider is confirmed degraded or unreachable.
Post-Incident Checklist
- Sentry issue linked to the incident notes.
- Coolify deploy ID and
/api/versionpayload recorded. - Correlation IDs captured for representative failures.
- User impact and duration recorded.
- Regression test added for code defects.
- Runbook updated when the response required undocumented knowledge.