LW IT Solutions
« Blog Overview /Digital Analytics / Server-Side GTM on GCP Cloud Run: Architecture,...
Read this article in other languages:

Server-Side GTM on GCP Cloud Run: Architecture, Auto-Scaling, and Cost Optimization

Part 3 of 5 in the series From pixel to server: tracking that holds

Server-Side GTM on GCP Cloud Run: Architecture, Auto-Scaling, and Cost Optimization
Contents
  1. Server-Side GTM on GCP Cloud Run: Architecture, Auto-Scaling, and Cost Optimization
  2. 1. Hardening the Auto-Provisioned Cloud Run Service
  3. 2. Configuring min-instances and max-instances
  4. 3. Memory Management, CPU Throttling, and Concurrency
  5. Summary
  6. Questions and answers
  7. Sources

Server-Side GTM on GCP Cloud Run: Architecture, Auto-Scaling, and Cost Optimization

Automatic provisioning of a Server-Side Google Tag Manager (ssGTM) server has created a Google Cloud Run service since autumn 2023 — Google App Engine is no longer the default environment. What the automatic setup delivers, however, is a minimal configuration meant for testing rather than for production traffic. Cloud Run itself provides a fully managed, stateless container environment with excellent auto-scaling responsiveness, fine-grained resource allocation, and a predictable cost model; unlocking that potential requires hardening the generated deployment deliberately.

1. Hardening the Auto-Provisioned Cloud Run Service

The legacy App Engine Flexible setup for ssGTM often led to overprovisioning during low-traffic periods and sluggish scaling during sudden traffic surges — one of the reasons Cloud Run replaced it as the provisioning default. Cloud Run operates on standard OCI (Open Container Initiative) Docker images, executing the ssGTM container (gcr.io/cloud-tagging-10302018/gtm-cloud-image:stable) entirely serverless. Automatic provisioning, though, leaves the service at settings that are adequate for testing but not for production volume. The flags described below turn that starting point into a deployment that absorbs load spikes within seconds instead of dropping hits.

Top: a browser hit reaches the Cloud Run service sgtm-production with warm instances of 512Mi and 1 vCPU for up to 80 requests each, gets 200 OK and the service then calls GA4, Meta Conversions API and TikTok Events. Below, five cards explain min-instances, max-instances, memory and CPU, no-cpu-throttling and concurrency 80.
The request path through server-side GTM on Cloud Run and the five deployment flags that prepare the service for production traffic.

2. Configuring min-instances and max-instances

The critical performance balance in Cloud Run lies in defining instance boundary flags correctly. Misconfiguring these boundaries either results in dropped e-commerce hits due to latency or excessive cloud billing.

  • min-instances (Eliminating Cold Starts): In standard serverless deployments, a container scales to zero when idle. The first incoming request triggers a fresh container startup, incurring a “cold start” delay of 2 to 5 seconds. For production tracking environments, setting --min-instances=1 (or higher for enterprise traffic) ensures that warm containers are always on standby, reducing hit latency to under 50 milliseconds.
  • max-instances (Budget Protection): Uncapped serverless scaling can lead to severe budget exhaustion during DDOS events or tracking loop anomalies. Defining a strict upper limit (e.g., --max-instances=10) protects Google Cloud Platform (GCP) quotas while easily accommodating Black Friday or promotional e-commerce peaks.

3. Memory Management, CPU Throttling, and Concurrency

Optimizing resource efficiency requires tuning container compute specifications to the asynchronous Node.js nature of the GTM server container:

# Recommended Cloud Run deployment command for Production ssGTM:
gcloud run deploy sgtm-production \
  --image=gcr.io/cloud-tagging-10302018/gtm-cloud-image:stable \
  --region=europe-west1 \
  --platform=managed \
  --allow-unauthenticated \
  --min-instances=2 \
  --max-instances=20 \
  --memory=512Mi \
  --cpu=1 \
  --concurrency=80 \
  --no-cpu-throttling \
  --set-env-vars="CONTAINER_CONFIG=aW52YWxpZF9iYXNlNjRfZXhhbXBsZQ=="
  • Memory and CPU Allocation: A typical ssGTM instance processing GA4, Meta Conversions API, and TikTok Events requires 512Mi of memory and 1 vCPU. Allocating more than 1 vCPU per container is rarely beneficial, as horizontal scaling handles volume more efficiently than vertical compute additions.
  • CPU Throttling (–no-cpu-throttling): By default, Cloud Run throttles CPU access outside of active request processing. Because ssGTM relies on background batching and asynchronous API dispatches (e.g., sending HTTP requests to Meta CAPI after returning a 200 OK to the browser), disabling CPU throttling is mandatory to prevent incomplete network requests.
  • Concurrency Settings: Cloud Run can process multiple simultaneous requests per container instance. Setting --concurrency=80 allows a single 512Mi container to handle up to 80 concurrent analytics requests before spinning up an additional instance, drastically cutting computing costs.

Summary

Deploying Server-Side GTM on GCP Cloud Run establishes a high-performance, containerized analytics gateway. Setting appropriate minimum instance thresholds prevents latency-inducing cold starts, while disabling CPU throttling and optimizing container concurrency guarantees reliable, high-volume e-commerce event processing at a predictable price point.

Questions and answers

With –concurrency=80 on 512Mi and one vCPU, which runs out first under real load, memory or CPU?

Usually memory, in that configuration, and it fails less visibly than CPU does.

Concurrency and compute are different levers: concurrency decides how many requests are admitted into one instance, CPU decides how quickly each is worked through. Under pressure a CPU shortage shows up as latency, which is measurable and eventually triggers another instance. A memory shortage ends the instance, and every request it was still holding — including the vendor calls dispatched after the 200 — disappears with it. Nothing in the reports says so; the hits are simply not there.

With three destinations per event, as in the article’s example of GA4, Meta Conversions API and TikTok Events, 80 concurrent requests each hold their payload and the pending outbound calls at the same time, and that is where 512Mi gets tight. Two numbers make the situation legible: instance count against request count, and the container’s memory utilization at peak. Where memory sits near the limit while CPU has room, the useful change is lower concurrency rather than a bigger instance — smaller batches of work per container, spread over more of them.

Is there a middle ground between cold starts and the standing cost of –min-instances=2, which accrues at night just as at noon?

Yes, in three steps, and the third is where the bill is actually made.

First, the number is not a permanent state: a schedule that lowers it to one instance at night via gcloud run services update and raises it again in the morning is a single cron entry and adds hardly any complexity. Second, a cold start only hits the first hits after an idle phase; for measurement data that is tolerable, for conversions it is not. The decision therefore depends on the type of day, not on the container.

Third, and this weighs more than both: with --no-cpu-throttling, billing is instance-based, covering the entire lifetime of the instance rather than only the time spent on requests. Two minimum instances without throttling therefore mean two vCPUs paid around the clock, regardless of traffic. Saving on the bill starts with checking this combination, not the number of hits.

Apart from latency, what should decide the Cloud Run region for a server-side GTM container?

Three things besides latency, and latency itself is usually the least important, because the differences between European regions are measured in milliseconds.

The first is the place of processing. The container receives the visitors’ complete requests, so questions about where processing happens apply to it, not only to the analytics vendor. The second is the cost of traffic between regions: an export to BigQuery or queries to Firestore in another region are billed, and at high volume that item stops being negligible. The third is service availability, because not every region offers the same set of services and the same limits.

A practical rule: the same region as the dataset the container talks to most often, and as close to the audience as possible. Changing the region after deployment means a new service with a new address, and therefore a change in the DNS of the own domain or in the tag configuration on the browser side — which is why the decision is best made once, before the first release.

From pixel to server: tracking that holds

  1. The Evolution of Web Tracking: From Log Files to the Server-Side Future
  2. GA4 & Server-Side GTM: The “Migrate from JavaScript Managed Client ID” Feature Explained
  3. Server-Side GTM on GCP Cloud Run: Architecture, Auto-Scaling, and Cost Optimization
  4. GA4 Measurement Protocol: Server-Side CRM Offline Conversion Integration
  5. Meta Conversions API: Maximizing Event Match Quality (EMQ) and Deduplication
Lukas Wojcik

Lukas Wojcik

Systems architect and technology enthusiast specializing in scalable tracking solutions, GMP Stack (GA4 & GTM), and robust backend architectures. Advocate for clean code and privacy-first design.

Get in Touch

Briefly describe your project or inquiry for a tailored response. This site is protected by reCAPTCHA.

Write a comment

Differing figures from other accounts and questions about the setup are welcome here.

The email address is not published. Required fields are marked with an asterisk.

Articles & categories

CCTV

Follow this category by RSS

Cloud & AI

All 17 articles in this category Follow this category by RSS

Data Privacy

All 19 articles in this category Follow this category by RSS

Digital Analytics

All 58 articles in this category Follow this category by RSS

Digital Marketing

All 37 articles in this category Follow this category by RSS

IT & Networks

All 19 articles in this category Follow this category by RSS

Music Production

All 17 articles in this category Follow this category by RSS

Raspberry PI

Follow this category by RSS

SaaS & Internet Earning

Follow this category by RSS

Smart Home

All 18 articles in this category Follow this category by RSS

Web Development

All 11 articles in this category Follow this category by RSS

WordPress Plugins & Tricks

All 14 articles in this category Follow this category by RSS