Azure Functions vs Cloud Run: We Ran the Same Worker on Both
Pick a serverless platform and you’re picking a default for the next five years of your stack. Most comparisons of Azure Functions vs Google Cloud Run are written from the docs. This one isn’t — we deployed the same worker to both, in production, on the free tiers, and watched what happened.
The worker is simple on purpose: it takes a webhook, does a little work, writes a record, returns JSON. The kind of glue every real system has dozens of. Boring is exactly what you want when you’re measuring the platform and not the app.
The short answer
If you just want the verdict: Cloud Run wins for anything containerized and anything where you care about not storing deploy keys. Azure Functions wins when your automation already lives in the Microsoft ecosystem and benefits from Logic Apps, Event Grid, and Entra sitting right next door. Both run our worker for $0/month. The tie-breakers are deploy security and what else is in the neighborhood.
Now the detail.
Deploying the same worker
This is where the two platforms feel most different, and where Google Cloud quietly pulls ahead.
How we do it
| Azure Functions | Google Cloud Run | Verdict | |
|---|---|---|---|
| Unit of deploy | Function app (code + host) | Container image | Cloud Run if you’re already containerized |
| Deploy auth | Publish profile / service principal | Workload Identity Federation — no stored keys | Cloud Run, decisively |
| Cold start | Noticeable on Consumption plan | Negligible at our scale | Cloud Run |
| Local dev parity | Functions Core Tools (good) | “It’s just a container” (great) | Cloud Run |
The headline is the deploy auth. Our Cloud Run workers deploy from GitHub Actions using Workload Identity Federation — GitHub proves its identity to Google with a short-lived token, and no service-account key is ever stored in the repo. That’s not a convenience; it’s the single biggest reduction in credential risk you can make in a CI/CD pipeline. Azure Functions can get close with OIDC + a service principal, but the container-native, keyless Cloud Run path was simpler to lock down and is the model we standardized on.
What the free tier actually gives you
Both platforms have genuinely generous always-free serverless tiers. The numbers that matter for a glue worker:
How we do it
| Metric | Azure Functions | Google Cloud Run | Verdict |
|---|---|---|---|
| Free requests/month | 1,000,000 | 2,000,000 | Google — 2× headroom |
| Free compute | 400,000 GB-s | 360,000 GiB-s + 180,000 vCPU-s | Roughly even |
| Scale to zero | Yes (Consumption) | Yes | Tie |
| Max instances control | Yes | Yes (and per-service concurrency) | Cloud Run, slightly |
| Our actual bill | $0 | $0 | Tie where it counts |
At our volume — thousands of invocations a month, not millions — both are free and stay free. The 2M-vs-1M request gap only matters if you’re genuinely high-traffic. For most glue workloads, you will never see a bill on either.
The neighborhood effect
A serverless function is rarely alone. It fires because something happened and it triggers something else afterward. That’s where the ecosystems diverge — and where Azure earns its keep.
- Azure Functions sits next to Logic Apps (4,000 free built-in actions/month), Event Grid (100,000 free operations/month), and Entra ID for identity. If your automation is event-driven and Microsoft-centric, the glue around the function is already there and already free.
- Cloud Run sits next to Eventarc, Cloud Workflows, Pub/Sub, and Cloud Scheduler — the same pattern on Google’s side, equally capable.
Neither is “better” in the abstract. The right answer is whichever cloud your other services already live in. A function that triggers a Logic App next door beats a function that has to reach across clouds to do the same thing.
What surprised us
- Cloud Run cold starts basically disappeared. At our concurrency the container was warm often enough that we stopped thinking about it. Azure Functions on the Consumption plan had more noticeable cold starts for the same workload.
- Azure’s free side-resources are real. Functions itself is free, but watch the storage account and Application Insights it provisions alongside — those can accrue tiny charges. Set a budget alert on day one.
- Keyless deploy changed our security posture more than any single config. Once the repo holds zero secrets for deploys, an entire category of “leaked key” incidents just can’t happen.
The takeaway
For a containerized, security-conscious, GitHub-Actions-driven stack, Cloud Run is our default — the keyless deploy and the request headroom settle it. But “default” isn’t “only”: when a workload belongs in the Microsoft ecosystem — triggered by Microsoft events, feeding Microsoft services, governed by Entra — Azure Functions is the right tool, and it runs for the same $0.
Run the same worker on both for a week. The platform stops being a religious debate and becomes a placement decision: put the work where its neighbors already are.
This is part of our “Two Clouds, One Site” series — we run the same media property on both Azure and Google Cloud, on the free tiers, and write up what we learn. The lab lives on tygart.media; the findings publish here.
Frequently asked questions
Is Azure Functions or Cloud Run cheaper?
For typical glue workloads, both are free and stay free. Cloud Run offers more free requests per month (2M vs 1M) and Azure offers 400,000 GB-seconds of free compute. At thousands of invocations a month you will not see a bill on either; the cost difference only appears at high traffic.
Which is more secure to deploy?
Cloud Run, because it supports keyless deploys via Workload Identity Federation — GitHub Actions authenticates with a short-lived token and no service-account key is stored in the repo. Azure Functions can approximate this with OIDC and a service principal, but the container-native keyless path is simpler to secure.
Can I run the same code on both Azure Functions and Cloud Run?
Yes. If you package the worker as a container, Cloud Run runs it directly and Azure Functions can run it via a custom handler or containerized function. We deploy the same worker logic to both; the differences are in deploy tooling and the surrounding event services, not the code.
When should I choose Azure Functions over Cloud Run?
Choose Azure Functions when your automation already lives in the Microsoft ecosystem — triggered by Event Grid, orchestrated by Logic Apps, or governed by Entra ID. Co-locating the function with the services it talks to beats reaching across clouds.
Do serverless cold starts matter on either platform?
At moderate concurrency, Cloud Run cold starts were negligible in our testing because the container stayed warm. Azure Functions on the Consumption plan showed more noticeable cold starts for the same workload. For latency-sensitive endpoints, test under your real traffic before deciding.