Start here
curl -s https://api.example.com/api/v1/health
docker compose -f docker-compose.prod.yml ps
docker compose -f docker-compose.prod.yml logs --tail=100 appCommon symptoms
| Symptom | Usual cause |
|---|---|
| 502 from the API after a deploy | nginx cached the old app container's address. Restart nginx. |
| Orders pay but nothing provisions | Queue worker not running, or the server's connection test is failing. |
| No recurring invoices | Scheduler container not running. All billing automation is scheduled. |
| Sign-in succeeds then drops | SANCTUM_STATEFUL_DOMAINS, CORS_ALLOWED_ORIGINS or SESSION_DOMAIN does not cover the portal hostname. |
| Dashboard 403 with a licensing reason | The licence is bound to a different domain or installation than the one serving the request. |
| Passkey registration refused | The relying party is not the page's domain or a parent of it. Set PASSKEY_RP_ID. |
| Config change has no effect | Cached config. Run config:cache and restart the containers. |
| Emails never arrive | SMTP failures are logged, not surfaced in the UI. Check the app log. |
Queue recovery
Failed jobs are retained with their exception so they can be inspected and retried rather than lost.
docker compose -f docker-compose.prod.yml exec app php artisan queue:failed
docker compose -f docker-compose.prod.yml exec app php artisan queue:retry allTipWhen something asynchronous appears broken, check in this order: is the worker running, is the job queued, did it fail with an exception. Most reports resolve at the first step.