Back to blog
Best PracticesCloud SecurityGCPMonitoring & LoggingNetworking

Load Balancer Backend Logging Disabled on GCP: Why It Matters and How to Fix It

Learn why disabled GCP load balancer backend logging is a security and observability risk, plus CLI, Terraform, and policy-as-code fixes to enable it for good.

TL;DR

This check flags GCP load balancer backend services that have logging turned off, which leaves you blind to traffic patterns, error spikes, and abuse. Enable it with a single gcloud compute backend-services update command and set a sample rate that fits your traffic volume.

When something goes wrong behind a load balancer, the first question is always the same: what was the traffic doing? Without backend service logging, you cannot answer that. You lose visibility into request latency, HTTP status codes, backend selection, and the client details that help you separate a legitimate spike from an attack. The Lensix lb_nologging check catches this gap by flagging any GCP load balancer backend service that has logging disabled.


What this check detects

GCP external and internal HTTP(S) load balancers route traffic through backend services. Each backend service has an optional logConfig block that controls whether request logs are emitted to Cloud Logging. The check inspects every backend service in scope and reports the ones where logConfig.enable is either unset or false.

When logging is off, the load balancer still routes traffic correctly, but it generates no per-request records. You get no entry in Cloud Logging showing the request URL, response code, backend instance that served the request, latency, or client IP.

Note: Backend service logging is separate from VPC Flow Logs and from the access logs your application emits. Flow logs capture network-level metadata, and app logs depend on your code. Load balancer logs sit in between and are the only place that records how the LB itself handled each request, including which backend it chose and why a request failed before reaching your instances.


Why it matters

Logging on a load balancer is not a nice-to-have. It is often the difference between a quick incident resolution and hours of guesswork.

You cannot investigate what you did not record

Load balancer logs are usually the first thing an engineer reaches for during an incident. A sudden jump in 502 or 503 responses, a latency regression, or a flood of 401s all show up in these logs before they show up anywhere else. If logging was disabled before the incident started, that data does not exist retroactively. You are stuck reconstructing events from incomplete sources.

Security blind spots

Attackers probe load balancers constantly. Credential stuffing, path traversal attempts, and scanner traffic all leave a fingerprint in request logs: unusual user agents, repeated requests to sensitive paths, bursts from a single IP range. Without logs, you cannot detect these patterns, feed them into a SIEM, or build alerts around them. A DDoS or Layer 7 abuse campaign can run for a long time before anyone notices.

Compliance and audit gaps

Frameworks like PCI DSS, SOC 2, and HIPAA expect you to log access to systems handling sensitive data. A load balancer fronting a payment API or a health records service with logging disabled is a finding waiting to happen during an audit.

Warning: Cloud Logging charges for log ingestion beyond the free tier (currently 50 GiB per project per month). High-traffic load balancers can generate large log volumes, so enabling logging at a 100% sample rate on every backend service may have a real cost. Tune the sample rate per service and route logs to a sink with retention that matches your needs.


How to fix it

You enable logging on the backend service itself. The fix takes one command, but you should choose a sample rate that matches your traffic.

Option 1: gcloud CLI

Enable logging with a sample rate. A rate of 1.0 logs every request, 0.1 logs ten percent.

# Global (external) backend service
gcloud compute backend-services update my-backend-service \
  --global \
  --enable-logging \
  --logging-sample-rate=1.0

# Regional (internal) backend service
gcloud compute backend-services update my-backend-service \
  --region=us-central1 \
  --enable-logging \
  --logging-sample-rate=1.0

Verify the change:

gcloud compute backend-services describe my-backend-service \
  --global \
  --format="yaml(logConfig)"

You should see:

logConfig:
  enable: true
  sampleRate: 1.0

Tip: For busy public-facing load balancers, start at a sample rate of 1.0 for a week to understand your baseline, then drop it to 0.25 or lower once you know what normal traffic looks like. For low-traffic internal services, leave it at 1.0 since the volume is small and full fidelity costs almost nothing.

Option 2: Google Cloud Console

  1. Go to Network Services → Load Balancing.
  2. Click the load balancer, then click Edit.
  3. Open the Backend configuration section and select the backend service.
  4. Expand Logging and toggle it on.
  5. Set the sample rate, then click Update.

Option 3: Terraform

If you manage infrastructure as code, add a log_config block to the google_compute_backend_service resource. This keeps the setting from drifting back to disabled.

resource "google_compute_backend_service" "default" {
  name        = "my-backend-service"
  protocol    = "HTTP"
  timeout_sec = 30

  log_config {
    enable      = true
    sample_rate = 1.0
  }

  backend {
    group = google_compute_instance_group.default.id
  }

  health_checks = [google_compute_health_check.default.id]
}

For a regional backend service, use google_compute_region_backend_service with the same log_config block.

Note: Logs land in Cloud Logging under the resource.type="http_load_balancer" filter. You can confirm logs are flowing with a quick query in Logs Explorer after generating some traffic. If nothing appears within a few minutes, double check the sample rate is above zero.


How to prevent it from happening again

Fixing one backend service is easy. Keeping every backend service compliant as your environment grows is the harder problem. The answer is to enforce logging at the point where infrastructure is defined and deployed.

Catch it in CI/CD with policy-as-code

If you provision load balancers with Terraform, scan your plans before they apply. A Conftest policy using OPA Rego can reject any backend service that ships with logging disabled:

package main

deny[msg] {
  resource := input.resource_changes[_]
  resource.type == "google_compute_backend_service"
  log_config := resource.change.after.log_config[_]
  log_config.enable == false
  msg := sprintf("Backend service '%s' has logging disabled", [resource.change.after.name])
}

deny[msg] {
  resource := input.resource_changes[_]
  resource.type == "google_compute_backend_service"
  count(resource.change.after.log_config) == 0
  msg := sprintf("Backend service '%s' has no log_config block", [resource.change.after.name])
}

Wire this into your pipeline so a merge cannot land without logging configured:

terraform plan -out=tfplan.binary
terraform show -json tfplan.binary > tfplan.json
conftest test tfplan.json --policy ./policies

Enforce with Organization Policy

GCP does not have a built-in org policy constraint that forces backend logging, so the practical guardrails are policy-as-code in CI and continuous detection. Run the Lensix lb_nologging check on a schedule so any backend service created out-of-band, through the console or a manual gcloud command, gets flagged within your normal scan cycle rather than discovered during an outage.

Tip: Pair detection with a remediation runbook. When the check fires, the fix is the same single gcloud compute backend-services update --enable-logging command every time, so it is a strong candidate for an automated remediation action that runs after a brief approval step.


Best practices

  • Enable logging on every backend service by default. Treat disabled logging as the exception that requires justification, not the norm.
  • Pick sample rates by traffic, not by guesswork. Full sampling for low-volume and security-sensitive services, reduced sampling for high-volume public endpoints where cost matters.
  • Route logs to a long-lived sink. Create a Cloud Logging sink to BigQuery or a Cloud Storage bucket so you can query historical traffic well past the default retention window.
  • Build alerts on the data. Logs you never look at have limited value. Set up log-based metrics for 5xx rates and latency, then alert on anomalies.
  • Keep the setting in code. Manage backend services in Terraform so logging cannot silently revert when someone recreates a resource.
  • Combine signals. Load balancer logs, VPC Flow Logs, and Cloud Armor logs together give you a full picture of edge traffic. Each fills a gap the others leave.

Backend logging is one of the cheapest forms of insurance in your GCP environment. The setting takes seconds to enable, and the first time you need to investigate a traffic spike or a security event, you will be glad the records exist. Turn it on, keep it on, and let policy-as-code make sure it stays that way.