Guides · Cloud Run & Google Cloud · Published 2026-09-12 · 2 min read

The Cloud Run /healthz Gotcha — Why That Exact Path Never Reaches Your Container, How to Prove It, and What to Name the Health Route Instead

On Cloud Run, a request to exactly /healthz is answered by Google's front end with its own 404 and never reaches your app, while /healthz/ and /health work. How to tell an edge 404 from an app 404 using response headers, and a naming convention that avoids the trap.

If you copy a Kubernetes habit and expose /healthz on a Cloud Run service, you will see something confusing: the route works locally, the deploy succeeds, and yet https://your-service/healthz returns a 404 that does not look like your app's 404. That is because it is not your app's 404.

What happens

Requests to the exact path /healthz are intercepted by Google's front end in front of Cloud Run and answered there with a generic 404 page. Your container never sees the request. Variants pass through normally: /healthz/ with a trailing slash, /health, /_health, /livez, /readyz all reach your app.

How to prove it is the edge and not you

Compare headers:

curl -sI https://your-service.run.app/healthz
curl -sI https://your-service.run.app/health

A response from your container carries an x-cloud-trace-context header and a server header set by your stack. The edge 404 has no trace header and a different, generic body. That header is the reliable tell for any "is it me or Google?" question on Cloud Run, not just this one.

What to do

Name the route /health and return a tiny plain-text body:

app.get('/health', (req, res) => res.type('text/plain').send('ok'));

Then use /health in uptime checks, smoke tests and load balancer probes. If you must keep /healthz for a shared tool, register it with a trailing slash and point the tool at /healthz/, but a different name is simpler.

A smoke test that catches it

After every deploy we hit the health route and assert both the status and the presence of the trace header, so an edge response can never pass as a healthy app:

const r = await fetch(`https://${host}/health`);
if (r.status !== 200 || !r.headers.get('x-cloud-trace-context')) throw new Error('health check did not reach the container');

Common mistakes

Summary

On Cloud Run, exactly /healthz is swallowed at Google's edge. Use /health, and in every smoke test check for the x-cloud-trace-context header to be sure a response came from your container.

Related guides