In the previous guide I covered sGTM setup on Cloud Run, Stape, and Docker self-host. This post is the decision side of the same topic: which hosting for which scenario, a production-ready Caddy pattern for self-host, agency multi-client setup, and the real role of Cloudflare Workers.
Hosting choice is not made by tool name but by weighing three axes together: maintenance capacity, data sovereignty, traffic predictability. This post puts the axes first and tool comparison second.
The sGTM Runtime Reality
The foundation of the decision: sGTM is a Docker image. The official image in Google Cloud Container Registry is gcr.io/cloud-tagging-10302018/gtm-cloud-image:stable, with the current base gcr.io/distroless/nodejs24-debian13, meaning Node.js 24 on distroless Debian. The previous version used Node.js 22 on distroless Debian 12.1
Runtime requirement: a container orchestrator capable of running Node.js. Cloud Run setup documentation recommends 1 vCPU and 500 MB RAM; in practice, the container consumes around 200 MB RAM at minimum load, and at high-traffic scale each instance takes a maximum of 1 vCPU (any more is wasted).2
The result: the sGTM hosting list is limited to platforms that can run Docker + Node.js. This list does not include Cloudflare Workers, Deno Deploy, Vercel Edge Functions, or Netlify Edge Functions. These are all V8 isolate platforms; they cannot run Docker images or long-lived Node.js servers. CF Workers can be placed in front of sGTM; I cover that in a separate section below.
Three Options, Three Profiles
| Option | Managed? | Region choice | Maintenance | Predictable cost |
|---|---|---|---|---|
| Google Cloud Run | Partially managed | 30+ regions | Low | No (usage-based) |
| Stape | Fully managed | EU, US, Asia, AU | Zero | Yes (fixed tier) |
| Self-host Docker | No | Fully flexible | High | Yes (fixed) |
| Google App Engine | Partially managed | 20+ regions | Medium | No |
App Engine has receded in favor of Cloud Run in current documentation, so I do not cover it separately here; the Cloud Run recommendation subsumes it. The actual decision is between Cloud Run, Stape, and self-host.
Cloud Run
Google Cloud Run is Google’s officially recommended path for sGTM. The manual setup guide documents Cloud Run deployment directly.3
Strengths:
- Native integration with GCP services: Secret Manager (container config and auth token management), IAM (client project isolation), Cloud Logging and Cloud Trace (no need for a separate debug collection layer).
- Native auto-scaling. Instance count adjusts to traffic; the max 1 vCPU per instance rule (more breaks auto-scaling) is in the written documentation.2
- Region variety: EU regions such as Frankfurt, Warsaw, or Milan.
- Best-documented path: primary sources like Simo Ahava, Mark Edmondson, and Square Developer Blog focus on Cloud Run.45
Weaknesses:
- Cost is unpredictable: as traffic grows, the usage-based bill grows with it; the advantage of fixed-tier models becomes visible during campaign days.
- Google Cloud billing setup in a client account typically requires documentation and an approval process. If the client does not have a GCP project, creating one adds an onboarding step.
- Cold start: if min instance is set to 0, the first request has latency. For Preview mode to work reliably, min 1 instance is recommended, which creates a fixed baseline cost.
- The preview container must be deployed separately. Preview events mixing into the production event stream pollutes reporting, so a separate Cloud Run service is opened for it.
Fits: Agencies deeply embedded in the Google ecosystem, GCP-familiar technical teams, variable traffic and scale needs, client accounts already using GA4 BigQuery export.
Does not fit: Agencies without time for maintenance, client-side GCP setup operations that drag on, scenarios where fixed monthly cost is required.
Stape
Stape is a managed service focused solely on sGTM hosting. The container runs on their side; the user only handles container config and tag mapping.6
Strengths:
- Zero ops. No contact with Docker, IAM, or billing layers.
- Region choice: EU (Frankfurt), US, AU, Asia.
- Ready-made templates called “power-ups” (CAPI, Enhanced Conversions, data enrichment, Cookie Keeper). Configurations that take time manually are enabled with a single click.
- The preview container is managed separately via a UI.
- A custom loader (serving the JS loader from their CDN) is used for ad blocker resilience.
Weaknesses:
- Pricing is tier-based; exceeding the tier limit forces a tier upgrade.
- Power-ups are paid add-ons; with several enabled, the total bill reduces the managed-only advantage.
- Container image cannot be modified; flexibility for custom logic is more limited compared to Cloud Run or self-host.
- Migration cost is higher once the stack is built on top of Stape.
Fits: Agencies managing multiple clients, teams wanting to shift maintenance load toward creative and strategy work, accounts where TR/EU region coverage is sufficient.
Does not fit: Clients with critical data sovereignty requirements (finance, public sector, health), advanced setups requiring custom container logic, scenarios where a fixed tier cannot absorb traffic surprises.
Self-Host Docker
Running the Docker image on your own server. Paolo Bietolini (December 2025) published a production-ready pattern: Docker Compose with a Caddy reverse proxy.7 In practice, two layers:
Production pattern: Docker Compose with two containers (preview + tagging), both bound to 127.0.0.1 ports, with Caddy providing HTTPS termination and subdomain routing (sgtm.site.com → tagging, sgtm-preview.site.com → preview). Critical Caddy notes: timeout ≥30 seconds (sGTM Preview mode holds some events for up to 20 seconds), cache disabled (Preview does not work with cached responses), X-Real-IP and X-Forwarded-For headers passed to the container.
Infrastructure: A VPS in EU regions like Hetzner Cloud, Caddy (automatic Let’s Encrypt), Docker. In multi-app environments, a PaaS layer like Coolify or Dokploy can be added; but since sGTM is a single service, running docker compose and Caddy directly is generally sufficient and offers less attack surface.
Alternative platforms:
- AWS ECS Fargate: Cloud Run-like serverless container, a natural choice for clients already in the AWS ecosystem.
- DigitalOcean App Platform: A lightweight alternative for simple deployment, with limited auto-scaling.
Setup essence (simplified from the Paolo Bietolini pattern):
# docker-compose.yml
services:
gtm_prod:
image: gcr.io/cloud-tagging-10302018/gtm-cloud-image:stable
environment:
CONTAINER_CONFIG: ${CONTAINER_CONFIG}
PREVIEW_SERVER_URL: ${PREVIEW_SERVER_URL}
ports:
- "127.0.0.1:8081:8080"
restart: always
gtm_preview:
image: gcr.io/cloud-tagging-10302018/gtm-cloud-image:stable
environment:
CONTAINER_CONFIG: ${CONTAINER_CONFIG}
RUN_AS_PREVIEW_SERVER: "true"
ports:
- "127.0.0.1:8082:8080"
restart: always
The container config string is found in the sGTM UI under Admin > Container Settings > Manual Provisioning. Caddy configuration, SSL, and log rotation details are documented in Paolo Bietolini’s guide.7
Local debug: If you want to run sGTM on your own machine, Simo Ahava’s docker-compose stack works smoothly with Colima (an open-source alternative that does not require a Docker Desktop license). I cover the details and steps in the sGTM setup guide.8
Strengths:
- Full data sovereignty. The physical server and data location are known.
- Fixed cost: monthly VPS fee, no extra bill within the traffic limit.
- No customization ceiling. The Docker image can be forked, custom middleware added.
- Short data transfer chain during KVKK and GDPR audits.
Weaknesses:
- Patch management, security updates, monitoring, backup, and SSL renewal fall into your responsibility (Caddy renews SSL automatically; the other layers are manual).
- Auto-scaling is manual. If the VPS falls short during a traffic spike, downtime happens.
- Preview and prod separation, reverse proxy, and firewall setup are manual.
- sGTM image updates must be tracked manually; a test layer is required during Node.js major version transitions (24 to 25 is coming).
Fits: Agencies managing a small client portfolio, with a DevOps team in place, data sovereignty in the client contract, and fixed cost as a requirement.
Does not fit: Agencies without DevOps capacity, high client variety (different traffic profiles require different sizing), scenarios requiring fast onboarding.
Additional Layer: Cloudflare Workers: Same-Origin Proxy
In the sGTM ecosystem, Cloudflare Workers is a transparent proxy placed in front of sGTM. Same principle as Google’s own official “Google Tag Gateway” concept.
What it does:
The visitor browser calls https://site.com/metrics. The CF Worker takes this request and forwards it to the sGTM endpoint running on Cloud Run (or Stape, or self-host). The response comes back and the Worker returns it to the browser. To the user, all analytics traffic appears to stay on the site.com domain.
What it gains:
- First-party cookie: The browser sets the
site.comcookie; cross-site restrictions do not apply. - Safari ITP: When set as a first-party server-set cookie, it is exempt from Safari’s 7-day restriction on JS-set cookies.
- Edge latency: The Worker runs on Cloudflare’s global edge network, responding from the closest point to the user.
- Ad blocker resilience (partial): Because your own domain path is used instead of known GA/Meta endpoint paths, simple list-based blockers may not recognize it. Aggressive blockers work ID-based, so this is not a full bypass.
Critical: CF default caching must be disabled. sGTM Preview Mode does not work with cached responses; debug breaks.9
Open source example: simondahla/sgtm-same-origin-proxy-cloudflare-worker provides ready Worker code.10 owntag published a detailed write-up on the same pattern.11 Stape provides a Cloudflare Worker setup walkthrough from its own management panel.12
Recommendation: Whatever hosting you choose, adding a CF Worker proxy layer in production is worth considering. The real gains are first-party cookies and ITP resistance.
Agency Multi-Client Architecture
For agencies managing multiple clients, three architectural paths:
Path A — Full isolation: A separate Cloud Run project or separate Stape account per client. Cleanest, highest ops load.
Path B — Shared infrastructure, separate container: Under a single agency Cloud Run project, a separate service per client (sgtm-clienta, sgtm-clientb). In a self-host scenario, separate Docker Compose services on a single VPS provide the same pattern. Stape does not support this model. This is usually the default agency model.
Path C — Single container, multiple container IDs: sGTM supports multiple container IDs in the same instance. If traffic is low, one instance can serve multiple clients, but there is no isolation: when one client’s event is debugged, the other is affected. Works for the agency MVP phase; with many clients, lack of isolation creates problems.
Client departure scenario:
- Cloud Run: Project ownership transferred to the client account via IAM transfer.
- Stape: If the account is opened in the client’s name, billing transfer is sufficient.
- Self-host: Docker compose and
.envare moved to the client’s server.
A handover checklist should be in the agency contract annex: DNS handoff, IAM transfer, ESP and Cookie Keeper cancellations, GA4 property ownership.
Decision Matrix
| Scenario | Recommended | Why |
|---|---|---|
| Small-to-mid agency, no DevOps team | Stape EU region | Zero-ops, fast onboarding, fixed tier pricing |
| Client deep in Google ecosystem, using BigQuery | Cloud Run | Native integration with GCP services, flexible scale |
| Enterprise client, data sovereignty in contract | Self-host (Hetzner + Caddy) | Full control, short KVKK audit chain |
| Multi-client agency, standardization is priority | Shared Cloud Run project | Shared infrastructure, separate service, template deploy |
| Low-traffic TR e-commerce | Cloud Run with min 0 instance | Cold start is tolerable, low cost |
| Ad blocker issue is front and center | Any + CF Worker proxy | First-party cookie and ITP resilience |
A CF Worker same-origin proxy on top of any option should be considered the default; it is not a standalone hosting choice but a natural layer on every stack.
Closing Note
The sGTM hosting decision cannot be reduced to the Cloud Run vs Stape binary. The decision starts on three axes (maintenance capacity, data sovereignty, traffic predictability) and branches based on agency and client profile. Tool names change; the axes remain.
For setup details, see the sGTM Setup Guide. The remaining layers of the agency marketing stack will be covered in the upcoming Marketing Stack 2026 pillar post.
Footnotes
- Manual setup guide. Google Tag Manager ↩
- Cloud Run Setup Guide. Google Tag Manager ↩ ↩2
- Manual setup guide. Google Tag Manager ↩
- Deploying Server-Side Google Tag Manager on Cloud Run. Square Developer Blog ↩
- Google Tag Manager Server Side on Cloud Run - Pros and Cons. Mark Edmondson ↩
- Google Tag Manager Server-Side Tagging with Stape. Analytics Mania ↩
- Implementing Server-Side GTM with Docker: On-Premise Solution Guide. Paolo Bietolini ↩ ↩2
- Run Server-side Google Tag Manager On Localhost. Simo Ahava ↩
- Same-origin Deployment With Server-side Google Tag Manager. Simmer ↩
- sgtm-same-origin-proxy-cloudflare-worker. simondahla (GitHub) ↩
- How to Make Your Server-Side GTM Accessible for Free via Cloudflare on Your Main Domain and Bypass ITP. owntag ↩
- How to Use Same Origin Through Cloudflare. Stape ↩
- 01 sGTM is a Docker + Node.js container and does not run on V8 isolate platforms like Cloudflare Workers
- 02 Cloud Run is the best-documented path, Stape is the zero-ops alternative, self-host is for data sovereignty
- 03 CF Workers runs as a same-origin proxy in front of sGTM, providing first-party cookies and ITP resistance
- 04 In agency multi-client setups, a separate container per client with shared infrastructure is the cost-effective model
- 05 The hosting decision is made on maintenance load and data sovereignty axes, not cost alone
+ Can I run sGTM on Cloudflare Workers?
No. sGTM is a Docker image (gcr.io/cloud-tagging-10302018/gtm-cloud-image:stable) and requires a Node.js runtime. Cloudflare Workers is a V8 isolate platform and cannot run Docker containers or long-lived Node.js servers. CF Workers can only be used as a same-origin proxy in front of sGTM.
+ Is Cloud Run or Stape cheaper?
It depends on traffic profile and maintenance time. For low-to-medium traffic, Cloud Run bills by usage, while Stape's fixed tier becomes predictable at high traffic. On the agency side, also factor in hourly maintenance cost.
+ Should the preview container be hosted separately?
Yes. Google's tagging server documentation recommends running the preview container as a separate instance; otherwise, preview events pollute the production event stream and cause reporting inconsistencies.
+ When using Stape, does data leave Turkey?
Stape offers EU region selection, but it does not guarantee that traffic stays entirely within Turkey. If KVKK compliance requires handling cross-border data transfer cases, self-host is preferred.
+ How many clients can a single sGTM instance serve?
A single container can be configured with multiple container IDs. In agency practice, a separate container per client is preferred for isolation; under a shared Cloud Run project, each client is deployed as a separate service.
+ Are CAPI and Enhanced Conversions dependent on hosting choice?
No. CAPI and Enhanced Conversions are configured in the sGTM container and are independent of hosting. Cloud Run, Stape, and self-host offer the same functionality.