GitLab health check endpoints for load balancers and Kubernetes

GitLab's readiness and liveness endpoints answer different questions, so each load balancer and Kubernetes probe needs the right one, an allowlist for monitoring hosts, and a rule that keeps health checks out of autoscaling decisions.

On this page

Which GitLab health check endpoint belongs in your load balancer

Put /-/readiness in the load balancer's health check and in a Kubernetes readiness probe, and use /-/liveness only in a liveness probe that decides whether a container should be restarted. Readiness answers whether an instance can serve requests now, so a failing check should take that node out of rotation. Liveness answers whether the process is still running. If a team points a liveness probe at a check that depends on PostgreSQL or Redis, a slow dependency can cause restarts that make the outage worse. Do not use either endpoint as a signal for autoscaling.

The /health_check endpoint is older and is aimed at monitoring systems that want more detail about the instance and its components. It is usually restricted by access rules, and its output is not something a load balancer should parse for routing decisions. Exact response bodies, status codes and the allowlist settings that control access change between GitLab versions, so confirm each one in the documentation for the release you run before go-live. Plan these checks before go-live and again before any multi-node or Kubernetes layout, because the probe paths, timeouts and intervals shape how failover behaves.

Before you rely on any endpoint, test it from the same source addresses your load balancer or monitoring host will use, not from an administrator's workstation, because access rules are applied by source IP. Add those monitoring hosts to the allowlist for /health_check only as the documentation for your version describes, and record the version you checked. Repeat the test at every upgrade stop, since a changed endpoint can silently mark healthy nodes as down. For scaling decisions, use metrics collected by your monitoring stack instead of a health endpoint, and confirm which metrics your release exposes.

Health check options compared by question they answer

This table compares each GitLab health check option by the question it answers, who usually calls it, and the access and fit points to confirm. Read it by first identifying your layout (single Linux package node, multi-node reference architecture or Cloud Native Hybrid), then matching each consumer to the endpoint that answers its question.

Endpoint or methodQuestion it answersTypical consumerAccess to confirm and fit
/-/readinessCan this node accept traffic now?Load balancer or Kubernetes readiness probeConfirm which networks can call it without login. Fit: the main signal for removing a node from rotation in multi-node layouts.
/-/livenessIs the web process still running and responding?Kubernetes liveness probeConfirm the probe source IPs are allowed. Fit: restart decisions only. Do not tie restarts to outages of external dependencies.
/health_checkIs the instance healthy overall, as a monitoring view?Monitoring host or external uptime checkerConfirm the token or IP allowlist for your version. Fit: monitoring and alerting, not autoscaling or load balancer gating.
Component checks (Gitaly, PostgreSQL, Redis, Sidekiq)Is a specific tier healthy and under what load?Prometheus or a monitoring host on the internal networkConfirm exporter ports and firewall rules per node. Fit: multi-node reference architectures where tiers run on separate hosts.
Cloud Native Hybrid probesAre stateless pods ready, separately from stateful services?Kubernetes probes and separate monitoring for VM or managed servicesConfirm probe network paths to VMs or managed services. PostgreSQL and Redis are not run inside Kubernetes in this layout.
Autoscaler inputsHow much work is queued or in flight?Autoscaler reading Prometheus metricsConfirm which metrics your version exposes. Fit: scale on load metrics, not on /health_check responses.

Matching each probe to the endpoint it should call

Load balancers, Kubernetes probes and external monitors each answer a different question about a GitLab node, so they should not all call the same URL. The cards below set out which endpoint to point each consumer at, what failure it guards against, and where a check can take healthy capacity out of service by mistake. Confirm each choice in a test environment before it reaches production.

Traffic routing at the load balancer

The load balancer decides which GitLab web nodes receive user traffic, so its check should answer whether a node can serve requests now. Point it at /-/readiness and keep the health path it uses short and predictable. A failing check here removes the node from rotation, which protects users from errors but reduces capacity, so confirm how many nodes can fail before the pool is overloaded. Test the behavior by stopping a dependency in a non-production environment and watching what the balancer does.

Kubernetes readiness gates

A readiness probe controls whether a pod receives traffic through its Service, and it can be stricter than a liveness check without causing restarts. Use /-/readiness for this role so a pod that cannot yet reach its dependencies stays out of rotation while it recovers. Check that rolling updates wait for readiness before terminating old pods, since a readiness check that never passes will stall a deployment. Confirm the probe timing against your own startup times in the test cluster.

Kubernetes liveness restarts

A liveness probe tells the kubelet to restart a container, so it should only fire when the process itself is stuck. Use /-/liveness here, not a check that touches PostgreSQL, Redis or Gitaly. If a shared dependency slows down, a liveness check that reports it will restart healthy pods in a loop and make the outage worse. Set generous failure thresholds and confirm the behavior when a dependency is down in your own environment.

External uptime monitoring

An external monitor from outside the cluster or network tells you whether users can reach GitLab at all, covering DNS, certificates and the load balancer itself. Point it at the public URL and alert on repeated failures rather than single misses. Keep the monitor's source address on an allowlist if the health endpoints are restricted, and confirm that the allowlist covers the monitoring hosts you actually use. Review this alongside the Prometheus metrics you collect internally.

Autoscaling signals

Autoscaling should respond to load signals such as request rate, queue depth or CPU, not to /health_check. That endpoint reports the state of several components together, so a dependency problem can mark a whole pool unavailable and trigger scaling decisions that add no capacity. Use metrics from Prometheus for scaling inputs and keep health checks for routing decisions only. Confirm the scaling policy in a test environment under synthetic load before you rely on it.

How to wire GitLab health checks into a load balancer and probes

This sequence takes a self-managed GitLab instance from an unknown health check setup to verified readiness and liveness checks for load balancers and Kubernetes probes, with access limited to the monitoring hosts you approve. Each step ends with a test your team can repeat after every upgrade.

  1. Confirm the GitLab version and its endpoint documentation

    Record the exact GitLab version running on every node, then open the health check documentation for that version rather than relying on older examples or forum posts. Your platform team owns this step, and the output is a short note listing the version, the install method and the endpoints you intend to use. Confirm that /-/readiness and /-/liveness are documented for your version and that you understand what each one checks. Also note that /health_check is a different endpoint with a different purpose. Done when the note is filed with your change records and every consumer is named against a documented endpoint.

  2. Assign each endpoint to a specific consumer

    Decide which system calls which endpoint before touching any configuration. Load balancers and Kubernetes readiness probes usually need readiness, because it decides whether an instance should receive traffic. Liveness answers whether the process should be restarted, so it should drive restarts only. Monitoring systems may call the detailed health check endpoints that your version exposes, and those calls should be limited to your monitoring hosts. Write the mapping as a table with consumer, endpoint, expected response and owner. Done when every consumer has exactly one endpoint and nobody plans to use /health_check for scaling decisions.

  3. Set the access rule for monitoring hosts

    Restrict access to the health check endpoints by source IP or network, so that only approved monitoring hosts can reach the detailed checks. Confirm the setting name and file location for your install method in the current GitLab documentation, since the Linux package, Helm chart and Operator each handle configuration differently. Apply the change in a maintenance window or a staging environment first. Keep the load balancer and probe source addresses in mind, because a rule that blocks them can mark healthy nodes as failed. Done when the allowlist is deployed and documented alongside the list of approved networks and the reason for each.

  4. Configure the load balancer health check path and timeouts

    Point the load balancer health check at the readiness endpoint for the GitLab web tier, then set the interval, timeout and healthy and unhealthy thresholds. Do not copy values from examples. Ask the load balancer owner and the GitLab operator to agree on numbers based on observed response times in your own environment during normal load and during a backup or upgrade window. Confirm that the load balancer sends its probes from addresses that the allowlist permits. Done when the backend pool shows each node as healthy, and a stopped GitLab service on one node moves that node out of rotation within the thresholds you chose.

  5. Configure Kubernetes probes for cluster installs

    If the instance runs in a cluster, set readiness and liveness probes on the GitLab webservice pods using the endpoints mapped in step two. Keep liveness conservative, because a restart loop can make an outage worse, and set the initial delay and failure thresholds from your own startup measurements rather than defaults. Check how the chart you use exposes probe settings and confirm them against the chart documentation for your version. Done when the pods reach ready state after a rollout and a deliberately broken dependency causes readiness to fail without triggering restarts.

  6. Verify checks from an allowed and a non-allowed host

    Run a request to each endpoint from an approved monitoring host and expect a success response. Then run the same request from a host outside the allowlist and expect the request to be refused. Record the status codes, timestamps and source addresses. Next, stop a GitLab service on one node in a test environment and confirm that the load balancer and readiness probe both report it, and that the access logs show the probing sources. Done when the results match the expected table from step two and the evidence is stored with the change record.

  7. Recheck the setup after every upgrade

    Repeat the verification in step six after each GitLab upgrade, including patch releases, and after any change to the load balancer, network or cluster. Upgrades can change endpoint behavior or configuration keys, so compare the documentation for the new version with the note from step one before you close the change. Assign an owner for this review in your runbook. Done when the post-upgrade verification is recorded and the version note is updated, so the next person can see what changed and why.

Why /health_check should not drive autoscaling

A health check answers one question: should this node receive traffic right now? The /-/health and /-/readiness endpoints return a binary answer, and that is the right shape for a load balancer or an uptime monitor. Autoscaling needs a different kind of signal. It needs to know how loaded each tier is and how fast that load is growing. A node that passes its health check can still be close to saturation, and a node that fails can be failing for reasons that more nodes will not fix. Feeding a pass or fail result into a scaling loop turns a coarse availability signal into a capacity decision it was never built to make.

The risk becomes sharper when the failing dependency is shared. If PostgreSQL or Redis slows down, web pods may start timing out and failing checks. An autoscaler reading those failures could add web replicas, which open more database connections and more Redis requests against the same overloaded tier. The loop amplifies the fault instead of containing it. Scaling the web tier does not relieve a saturated Gitaly, PostgreSQL or Redis tier, because those components are stateful and sized separately, and the GitLab reference architectures describe their capacity in terms of users and API request rates. Confirm the intended use of each endpoint for your exact version in the GitLab documentation before you wire it to any automation.

Base autoscaling on load metrics from the Prometheus exporters bundled with GitLab, such as request rate, latency and saturation signals for each tier, and size each tier against the capacity guidance in the reference architectures. Keep the health check in its narrow role: the load balancer or Kubernetes readiness probe uses it to decide whether a single node receives traffic. Alert separately on dependency health for Gitaly, PostgreSQL and Redis, so an operator sees the shared fault instead of a scaling event. Ask your team to document which signal drives each scaling action and which signal drives each traffic decision.

Securing health endpoints without blinding monitoring

Health endpoints answer questions that load balancers, probes and monitoring hosts need answered, but they can also reveal more than an internet visitor should see. The cards below cover how to limit who can reach them, what those responses disclose, and how to keep the access rules reviewed and tested so that monitoring does not go dark after a network change.

Allowlist monitoring and load balancer sources

Restrict the health paths to the specific addresses that actually poll them: load balancer nodes, Kubernetes probe source ranges where they apply, and your monitoring hosts. Confirm with your network team which addresses leave each device, because NAT and proxies often change the source a GitLab node sees. Keep the rest of the instance, including the sign-in and API surfaces, under its own access rules.

Avoid broad public allowlists

An allowlist that includes large public or cloud provider ranges is not an allowlist in practice, because almost any internet host can fall inside it. Prefer single addresses or small, documented subnets for each monitoring system. If a vendor publishes a range for its probes, ask whether it is shared by other customers before adding it, and record the reason next to the entry.

Check what responses disclose

Fetch each health path from outside the allowed sources and read the full response and headers. Look for version strings, dependency names, hostnames, internal addresses or component states that an attacker could use for reconnaissance. Where the response carries more than a status, decide whether to restrict it further at the proxy and confirm the behavior after each GitLab upgrade, since response content can change between releases.

Keep the allowlist in version control

Store the allowed addresses, proxy rules and probe configuration in the same repository as your infrastructure code, so every change has an author, a reason and a reviewer. Require a second reviewer for any entry that widens access. Tie the rules to the change record used for GitLab upgrades and maintenance windows so that auditors and operators can trace who approved a given exposure.

Alert on blocked health requests

Log every denied request to the health paths at the proxy or load balancer, and alert when a source that used to succeed starts receiving denials. A sudden drop in allowed polls often means a changed IP, a moved monitoring host or a rule that now blocks a legitimate probe. Separate this alert from security alerts on unexpected sources, so that operators can act on each without confusion.

Retest after every network change

Run a scripted check from each allowed source and from one disallowed source after every firewall, proxy, DNS, cloud security group or GitLab host change. Include a check from the load balancer itself and from a Kubernetes node if probes run there. Record the results with the change ticket. Treat a failed allowed check as a blocked release, because monitoring that silently stops is harder to detect than an open endpoint.

Questions teams ask before setting up GitLab health checks

Which health endpoint should a load balancer use for GitLab?

Point the load balancer at the readiness endpoint, which tells it whether an instance can serve requests now, and reserve liveness for deciding whether a process has hung and needs a restart. Both live under the /-/ path on the GitLab external URL, and access to them can be restricted, so confirm which source address the balancer's probes will use before you configure anything. A readiness failure should remove the node from rotation and leave it running, so the instance can recover without a forced restart. Ask for written confirmation of the endpoint for each component on your installed version, the expected response, and how the check behaves when PostgreSQL or Gitaly is degraded. A web node can answer while its backing services are failing, so test that case explicitly before go-live.

Can a Kubernetes liveness probe restart GitLab during a backup or upgrade?

Yes. A tight liveness probe can fail while a component is busy with a backup, a migration or a heavy background job, and the kubelet will then restart the container at the worst possible moment. Set probe timeouts and failure thresholds with that work in mind, and keep liveness limited to a check that the process is alive. Confirm the probe values that the Helm chart, the GitLab Operator or your own manifests set for each component on the version you run, because defaults change between releases. Plan backups and upgrades inside a change window with maintenance mode, and check the upgrade path, since required upgrade stops apply to every route. Drivers include the install method, the number of nodes, where backups run and how much your change control requires. Ask for the final probe settings in writing and a test run in a non-production environment.

Should a failing GitLab health check trigger autoscaling?

Generally no. Autoscaling should respond to load signals such as request rate, queue depth or resource pressure, while a health check should decide whether a specific member can receive traffic. A health endpoint can fail because a database is down, a deployment is running or a backup is in progress, and scaling out on that signal adds instances that fail the same way. Scaling in during an incident can remove capacity you still need. Use Prometheus metrics as scaling inputs, set cooldowns, and keep alert thresholds owned by a named team. The sizing of your web tier should follow the published reference architectures for your user count and API request rate, which the reference architectures documentation describes. Runner fleets scale on their own configuration, so keep that separate. Ask for the scaling metric, the thresholds and the owner in the written scope.

How do we allowlist monitoring hosts behind a reverse proxy?

Allowlist the monitoring hosts by the address GitLab actually sees. Behind a reverse proxy, load balancer or ingress, the source address can be the proxy rather than the monitoring host, so the allowlist either blocks every probe or allows far more than intended. Configure the trusted proxy settings so GitLab reads the client address correctly, and confirm the exact configuration keys for your install method and version in the GitLab documentation before editing gitlab.rb or chart values. Keep the list narrow, naming specific monitoring servers or a small subnet rather than the whole internal network. Verify the result by requesting the health endpoints from each listed monitoring host and from one host that should be refused. Ask for the list of addresses in writing, a change process for adding hosts, and a review step during each upgrade.

Does this work need a partner, or can our own team do it?

An internal team can do it if it already runs self-managed GitLab, controls its load balancer and monitoring stack, and has a change process that covers probe and allowlist changes. A partner is more useful when the topology spans several nodes, the install is a Cloud Native Hybrid layout on Kubernetes, several teams consume the endpoints, or the change must be tested across environments before production. The main drivers are the install method, the node count, the network layout, the number of consumers and how formal your change control is. DeployOpen plans, implements, hardens, documents and supports self-hosted platforms in your own infrastructure, and most engagements are fixed-scope, with scope, deliverables and timelines agreed in writing before work starts. Ask any provider for a written scope listing the endpoints, probe settings, allowlisted hosts, tests and handover material.

What does a health check setup need from our team?

It needs access to the GitLab hosts or cluster, the load balancer and proxy configuration, the monitoring hosts' addresses, and a named approver for probe and allowlist changes. It also needs a complete list of consumers, including load balancers, Kubernetes probes, uptime monitors and Prometheus scrapes, because each one may expect a different endpoint or source address. Your team should be ready to provide a non-production environment for testing, a change window for the cutover, and someone who can confirm how upgrades are scheduled. Your team should also decide who receives alerts when a check fails, since an unowned alert is often the first thing removed during an incident. Ask the provider for a written list of your inputs, a test plan that covers both healthy and failing states, and a handover that names who maintains each setting after the work is complete.

How do health checks fit into GitLab maintenance mode?

Maintenance mode puts GitLab into a read-only state for activities such as upgrades, migrations and Geo failover, but health checks do not change their behavior on their own. Decide in advance whether the load balancer keeps routing traffic during maintenance, whether readiness should fail so traffic drains, and whether monitoring alerts are silenced for a defined window. Those choices depend on how many nodes you run, whether the upgrade is planned as zero downtime, and which tier you license, so confirm the maintenance mode requirements for your edition. Document the order of steps: enable maintenance mode, drain or hold traffic, perform the change, confirm readiness, then return to normal routing. Before any upgrade, review the upgrade paths documentation so the required stops are part of the same plan. Ask for this sequence in writing.

Limits to confirm in your environment before go-live

The health check endpoints behave differently depending on GitLab version, install method and what sits in front of the instance. The items below are the points we confirm against your team's version and layout during scoping, so the probes and allowlists work on the day you go live.

Exact endpoints and response codes

Confirm which probe paths, status codes and access settings apply to the GitLab version you will run, and whether each endpoint returns a body that load balancers can match. Test each path from the load balancer or kubelet itself, not from a workstation, because the answer depends on the source address. Record the results so a later upgrade has a known baseline to compare against.

IP allowlist configuration key and file

Identify the configuration key and file that control which monitoring hosts can reach the health endpoints on your install method, for example the Linux package's gitlab.rb or the Helm chart values. Confirm the key name against your installed version, since the setting can differ between install methods. Keep the allowlist limited to the monitoring hosts and document who owns changes to it.

Host headers and custom load balancer headers

Check whether your load balancer can send the host name the instance expects and any custom headers your access rules require. A probe that connects by IP address or with a generic host header can fail even when GitLab is healthy. Agree on the exact host header in the load balancer configuration and test it after every change to DNS or certificates.

Behavior behind ingress or a reverse proxy

Confirm how probes travel through Kubernetes ingress or a reverse proxy, including which source address GitLab sees and whether the proxy forwards the health paths at all. Some proxies block or rewrite requests to paths under /-/, which hides failures from the load balancer. Validate the whole path from the probe source to the GitLab pod or service.

Health checks during maintenance and upgrades

Decide how probes should react when the instance is in maintenance mode or during a multi-node upgrade, when a node may report unhealthy on purpose. Agree with your operations team whether a node should be removed from rotation, and how long a failed probe may persist before action is taken. Test this behavior against a non-production upgrade before the first required upgrade stop.

Component checks in reference architectures

Confirm whether the reference architecture you run needs checks beyond one endpoint, since a single probe reports on the web application rather than every stateful component. In larger layouts, Gitaly, PostgreSQL, Redis and Sidekiq each need their own monitoring, which the Prometheus guidance on component tiers covers. Decide which checks are used for load balancing and which only for alerting.

How DeployOpen scopes and delivers GitLab health check work

DeployOpen treats health check endpoints as part of the GitLab deployment design, not an afterthought. We agree in writing which probes, load balancer rules and monitoring allowlists your instance needs, then build and verify them inside your own infrastructure.

How we scope

  • The written scope lists each load balancer, Kubernetes probe and monitoring host that will call GitLab endpoints.
  • Scope names the install method and topology, so readiness and liveness rules match the actual deployment.
  • Engagements are fixed-scope, with deliverables and timelines agreed in writing before work starts.

How we build

  • We configure load balancer health checks against /-/readiness and probes against /-/liveness, with paths and timeouts recorded.
  • We restrict access to health endpoints with an IP allowlist covering only the monitoring hosts you name.
  • We test each probe under normal and degraded conditions and confirm autoscaling uses metrics, not /health_check.

How we hand over

  • You receive a written record of each endpoint, its consumer, its allowlist entries and the expected responses.
  • Runbooks explain what a failing readiness check means and which component to inspect first.
  • Configuration is kept in version control so changes to probe settings go through review like any other change.

How we support

  • Ongoing support, upgrades and continuous testing are available as retainers after handover.
  • Health check rules are rechecked during each planned GitLab upgrade, including required upgrade stops.
  • Ask any partner to confirm endpoint behavior against the GitLab version you run before relying on it.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.