From AWS Lambda to Cloudflare Workers: free tiers and cold starts

September 11, 2026 Telegram Aws Lambda S3 Cloudflare Workers R2 Go



In the previous article I described how I fitted a Telegram volleyball organizer bot into the AWS Free Tier: Lambda + S3 + EventBridge, at about zero dollars. That setup ran for months. Then I moved the same bot to Cloudflare Workers and R2 — the same Go, the same JSON state files, the same Gemini router.

Why touch something that was already free? Cold start. A Lambda on the provided.al2023 custom runtime wakes up in hundreds of milliseconds after idle time, sometimes more than a second. You feel that on a Telegram webhook: the first update after a quiet stretch is slower than the next one. A Workers isolate comes up in tens of milliseconds. On a real deploy of this bot, Wrangler reported Worker Startup Time of 16–37 ms.

Below is a practical comparison of AWS, GCP, Azure, and Cloudflare free tiers for the two things this bot needs: Lambda-style compute and S3-style object storage. Numbers are a snapshot for September 2026 — I always re-check the official pages before production.

Cold start comparison

Same bot, different runtime

The product did not change: Telegram webhook, Gemini as a router, JSON state for games and chat memory, pre/after-game jobs, and a Gmail poll for rent payments.

On AWS that meant several Lambdas and EventBridge one-shots (at(...)) per game. On Cloudflare:

  1. One Go Worker compiled to Wasm with syumai/workers-go.
  2. The same object keys in R2 that used to live in S3 (state/game_state.json and friends).
  3. Instead of EventBridge, a JSON job calendar in R2 and a cron every 10 minutes that runs whatever is due.

Workers have no one-shot “wake me on 12 September at 15:30”. They also have no zoo of functions: webhook and cron are the same binary with two entrypoints.

Compute: Lambda-like services

AWS LambdaGCP Cloud Run functionsAzure Functions (Consumption)Cloudflare Workers
Free invocations1M / month, always free2M / month, always free1M / month (Consumption grant)Free: 100,000 / day (~3M / month). Paid: 10M / month in the $5 plan
Compute400,000 GB-s / month400,000 GB-s + 200,000 GHz-s400,000 GB-sFree: 10 ms CPU per invocation. Paid: 30M CPU-ms / month
What “duration” meanswall-clock × memorywall-clock × memory/CPUwall-clock × memoryCPU time, not HTTP wait
Cold starthundreds of ms (Go custom runtime)hundreds of ms … secondsoften secondstens of ms (isolate)
Gonative provided.al2023nativecustom handlerWasm (GOOS=js)

Sources: AWS Lambda pricing, Google Cloud Free Tier, Azure Functions pricing, Workers pricing, Workers limits.

The three hyperscalers look alike: millions of requests and hundreds of thousands of GB-seconds. That is enough for a small bot. The real difference is how the runtime wakes up, and whether the storage free tier expires after a year.

Cold start

Classic Lambda boots a micro-VM, pulls a runtime, then your zip/image. For Go on provided.al2023 that is usually hundreds of milliseconds. GCP Gen2 is closer to Cloud Run: better than first-gen Functions, still a container cold start. Azure Consumption is the worst of the four: after idle, the first request often lands in seconds.

Workers are not containers. They are V8 isolates. Cloudflare’s startup limit is one second; my Wasm worker actually started in 16–37 ms. Warm isolates are faster still. For a chat bot that matters more than the “1 million requests” row: people notice a pause, not GB-seconds.

Billing is different too. While the Worker waits on Gemini, wall-clock passes and CPU barely moves. Lambda charges for the whole time the function is alive. Workers count CPU time, not seconds spent waiting on HTTP.

This bot runs on Workers Free

Workers Free is generous on request count: 100k/day is already more than always-free Lambda (1M/month). Since 4 September 2026, Free and Paid share one size limit: 64 MiB uncompressed. My Go Wasm is about 39 MiB Total Upload, so it deploys without an upgrade.

10 ms CPU per Free invocation sounds tight for a Gemini bot, but waiting on HTTP barely burns CPU. While the model thinks, the isolate is idle on the network. Production for this bot stays on Workers Free: Subscriptions shows Workers Free, not $5/month.

Paid at $5 is worth it if you hit the 10 ms CPU cap or 100k requests/day. I have not needed it yet.

R2 may show up as its own product (R2 Paid) — that is how Cloudflare turns storage billing on. The always-free allowance remains: 10 GB, 1M Class A, 10M Class B. For JSON bot state that is still zero dollars.

Object storage: S3 and cousins

AWS S3GCP Cloud StorageAzure BlobCloudflare R2
Free storage5 GB for the first 12 months5 GB-month always free, only us-central1 / us-east1 / us-west15 GB LRS for the first 12 months (Free Account)10 GB / month, always free
Reads20,000 GET / month (year 1)50,000 Class B~20,000 reads (year 1)10M Class B / month
Writes2,000 PUT / month (year 1)5,000 Class A~10,000 writes (year 1)1M Class A / month
Egresscapped, then $/GB100 GB (limited regions)billed separatelyfree
After the grant~$0.023/GB, PUT $0.005/1knormal GCS ratesthe storage account is not in the Functions grant$0.015/GB beyond the grant, still no egress

Sources: AWS S3 pricing, GCP Free Tier, Azure Functions pricing (storage billed separately), R2 pricing.

In the AWS article the S3 bottleneck was 2,000 PUT requests in year one. Lazy load and a single write at the end of the handler existed because of that. R2 allows a million Class A operations every month, always free. A bot that writes a few JSON files per update lives in a different order of magnitude.

Azure’s catch: the Functions grant does not cover the storage account created with every Function App. “Free functions” can still drip Blob charges.

GCP Cloud Storage is always free, but only in three US regions, and Class A is 5,000/month. Fine for JSON state, tight if you PUT on every message.

R2 also has no egress fee. For this bot that barely matters (state is tiny). As a free S3 analog it is the most honest line in the table: 10 GB + lots of ops + no “first year” asterisk.

What the migration actually changed

I did not rewrite the bot. The runtime and the scheduler changed:

  • GOOS=js GOARCH=wasm instead of linux/amd64;
  • http.DefaultClient via Workers fetch (plain net/http on JS dies with Illegal invocation);
  • Europe/Istanbul via embedded time/tzdata — Wasm has no IANA zoneinfo;
  • EventBridge one-shots became a job list in R2 plus cron */10 * * * *.

The accuracy trade-off: after-game can be up to 10 minutes late. Fine for “thanks for the game”. The win: one deploy, isolate start an order of magnitude faster than a typical Lambda cold start, and object storage whose always-free limits do not need to be massaged around 2,000 PUTs.

Conclusion

If you only compare “free serverless” by millions of requests, AWS, GCP, and Azure look almost the same. Add cold start and how long the storage grant lives, and the ranking changes.

  • AWS — strong always-free Lambda and familiar S3, but S3 generosity lasts a year, and Go Lambda cold start is noticeable.
  • GCP — more free function invocations; always-free storage only in three US regions.
  • Azure — similar Functions grant, Blob is extra, Consumption cold start is often the longest.
  • Cloudflare Workers — shortest start of the four (isolates; 16–37 ms on my deploy). The Free plan covers both requests and, since September 2026, a large Wasm bundle. R2 is the best always-free object tier: 10 GB, a million writes, ten million reads, no egress.

I parked this bot on Workers + R2. Not because AWS stopped being free, but because the first update after a pause no longer waits for Lambda to wake up.

Tags:

Test Your Knowledge

1. Which serverless runtime usually has the shortest cold start?
2. What is Cloudflare R2's always-free storage allowance?
3. Which statements about object-storage free tiers are true?

Related Articles

February 28, 2026

How I Deployed an AI Telegram Bot to AWS for Free

How I Deployed an AI Telegram Bot to AWS for Free

For over three years, I have been organizing volleyball games in our Telegram community. At first, we used standard Telegram polls, but the routine kept growing, so I decided to automate the process. That is how an AI-powered organizer bot was born, and the whole architecture is built around it.

Read More → Telegram Aws Lambda S3 Ai
December 20, 2024

Deploying Telegram Bot to AWS Lambda with Function URL

This article is a continuation of “Building an AI Telegram Bot with Go, Gemini API, and AWS Lambda” and contains detailed instructions for setting up and deploying a Telegram bot to AWS Lambda using Function URL.

Read More → Go Telegram Aws Lambda Deploy Function-Url Cli
December 19, 2024

Building an AI Telegram Bot with Go, Gemini API, and AWS Lambda

In this article, we’ll explore how to build an intelligent Telegram bot using Go that acts as a proxy between users and Google’s Gemini API. The bot will handle two primary functions: answering user messages and generating images. While this mechanism can be significantly extended with additional capabilities like voice and video generation, we’ll focus on these two request types for simplicity.

Read More → Go Telegram Gemini Ai Aws Lambda Bot