Team Meeting Bingo, and why Lambda Web Functions matter
AWS gave Lambda a way to run your own web server and hold a connection open. I built a joke bingo app to find out what that's actually for.
AWS gave Lambda a way to run your own web server and hold a connection open. I built a joke bingo app to find out what that's actually for.
A joke app about the worst bits of meetings, sat on top of something AWS launched this week that isn't a joke at all.
That's twelve bots playing bingo against a scripted team meeting. Every square is something you've probably heard this week: "Sorry, I was on mute." "Can everyone see my screen?" "This could have been an email." - well that last one is likely thought rather than said out loud. When somebody says one, every card with that square lights up, on every screen, as it happens.
So here's one I made earlier, and it's daft on purpose !
Anyone who knows me knows I'm bullish on Lambda and serverless. I got my start on AWS with Amazon Connect, automating IVRs (the "press 1 for billing" phone menus), so when I read about Lambda's new web functions I knew I wanted to see what I could build with them. I spent the last two evenings on this.
The thing underneath it launched on 12 October, and it changes what a Lambda function can be. So this post is about that, and about where I'd use one for real. (Spoiler: it's not the bingo app.)
The Lambda you know, now called an event function, gets an event, does a thing and hands back a result. One request per environment at a time, then it's done.
A web function runs your own web server instead. You write a perfectly ordinary HTTP server, it listens on the port Lambda hands it, and Lambda runs as many copies as the traffic needs. Each copy is an environment.
That changes more than it sounds like it should. One environment now handles lots of requests at once; in my runs a single environment peaked at 64 in flight, which was the ceiling I'd set. And a response can stay open, so the server keeps writing to the browser instead of answering and hanging up. That's how every card updates live. Each browser holds one stream open (Server-Sent Events, the plain HTTP kind) and the server pushes changes down it.
The catch is that there's no session affinity. Every request is routed on its own, so two requests from the same browser can land on different environments. Watch the badges in the GIF: twelve players spread over five environments, and no telling who lands where.
You deploy it as a function, a revision (an immutable snapshot of your code and settings) and an endpoint. The endpoint is the HTTPS address. It decides who's allowed to call it and how traffic splits between revisions, so canary releases come built in.
Live apps on AWS have always been a bit of a project. If you wanted a page that updates itself, the options looked like this.
| Option | What it costs you |
|---|---|
| API Gateway WebSockets | A table of connection IDs, a function per message, and code to post back to every connection. It works, but you're building plumbing. |
| A container on ECS or Fargate | Easy to write. Also sat there running at 3am when nobody's watching. |
| Polling | Every browser asks "anything new ?" every few seconds, and you pay for every time the answer is no. |
A web function gives you the container way of writing it, with Lambda doing the scaling. The bingo server is one node:http file with no framework, and it has no idea it's on Lambda. On my laptop it runs against DynamoDB Local. In AWS it's the same code.
Pricing is per request ($0.30 a million), per active vCPU-second ($0.0000276944) and per GB-second of memory ($0.0000036667).* You only pay for CPU while your code is using it, but memory is charged for as long as the environment is up, so a stream sat open waiting for the next phrase costs you mostly memory.
US East (N. Virginia) rates; Ireland pricing wasn't listed when I checked.
Take the jokes out and bingo is a pattern: lots of people watching the same thing change, live, with the occasional stampede. That pattern is everywhere. None of these are things I've built. They're where I'd reach for a web function first, and why.
| Where | What's live | Why it fits | The bingo version |
|---|---|---|---|
| Local government | Election count night: a results board as each ward declares | Quiet for hours, then everyone refreshes at once on every declaration | A phrase gets said and every card updates |
| Education | Results day and clearing places | Everyone turns up in the same few minutes, once a year | Hundreds of players joining at once |
| Healthcare | A&E or clinic waiting-time board | One number that lots of people watch all day | The live player count |
| Events and retail | Your place in the queue for a ticket drop | A burst of joins, then a long wait watching a number move | The lobby filling up |
| Any organisation | All-hands Q&A and live polling | Hundreds of people watching one screen while the votes land | Literally this app, minus the jokes |
| Transport | A live disruption board | Updates pushed as they happen | Phrases "said" on the meeting clock |
| Anything with AI in it | A model's answer streamed as it's written | Long responses that would otherwise sit behind a spinner | The event stream itself |
The steady state is easy in every one of these. It's the stampede that hurts. Keep that in mind for the end of this post.

Following the numbers:
Nothing in an environment matters if it disappears. Everything that does matter lives in DynamoDB, and the meeting script is worked out from the clock, so every environment agrees on what's been said without ever talking to the others.
Should everything move to web functions ? It depends. Here's where I wouldn't.
EventSource does that for you, mostly.If you do use one, set both guard rails on the endpoint: a cap on environments and a requests-per-second limit. Anything over either gets a 429, which beats finding out from the bill.
Twelve players is where a normal demo stops. Twelve tiles, five environments, one winner, round of applause.
So I sent 500 bots at it.
271 got in. The other 229 got an HTTP 500.
Before anyone starts the "Lambda doesn't scale" thread: Lambda was the best-behaved thing in the stack. It scaled and it answered every request. The error it handed back was mine, because the bug was in how I'd stored the game, and AWS did exactly what its documentation says it will - but whos got time to read the documentation!
Part 2 is the post-mortem: why 500 players broke it, why sending 1,000 got exactly two more in, and how I fixed it properly.
I designed and architected this one; Claude Code did a lot of the typing and most of the log trawling. The code is on GitHub. And if your Thursday all-hands needs livening up, you know where it is.