Skip to main content

Health and status

One endpoint and one docker command tell you whether the instance is up and which version is running.

The health endpoint

The api serves an unauthenticated health check at /api/v1/healthz:

curl -s http://localhost:8088/api/v1/healthz
{
"ok": true,
"service": "cobblr-api",
"env": "production",
"deploy_env": "production",
"build_sha": "a1b2c3d",
"time": "2026-07-11T15:04:05.000Z"
}
  • ok: true means the api is up and serving.
  • deploy_env is the label your instance shows in its environment chip.
  • build_sha is the running build. The app polls this so an open tab can notice it is behind after you update and offer a refresh. It is also how you confirm, from the outside, which version answered.

The endpoint is mounted ahead of authentication on purpose, so a health check is never gated behind a login. It is safe to point an uptime checker at it.

The container healthcheck

The api container has a built-in healthcheck that calls the same endpoint every 30 seconds. It gives startup a 60-second grace period (start_period) before a failing check counts against it, because the first boot after an update runs the database migrations and loads modules before the api listens. Read the current state with:

docker compose ps

You will see one of:

  • running (healthy): up and passing checks. Normal.
  • running (health: starting): inside the grace period, still booting. Give it up to a minute after an update.
  • restarting or running (unhealthy): the api is not coming up.

What a stuck deploy looks like

After docker compose pull && docker compose up -d, a healthy update settles to running (healthy) within a minute or so. A stuck one does not: the api stays in health: starting and then flips to unhealthy, or the container sits in restarting. That pattern almost always means a migration failed on the first boot, which crashes startup by design rather than serve a half-migrated database.

The reason is in the logs:

docker compose logs --tail=100 api

A failed migration names itself in that output. From there, the fix is to step back to the previous version: see Rollback. For reading logs in general, see Logs.