Understanding serverless computing
I can remember the serverless hype a few years ago. Social media were overflowing with content promoting serverless computing, displaying it as the infrastructure of the future. I haven’t checked any real data, but I think the hype has waned — yet the products remained and are still being used.
Personally, I was also hyped by the serverless concept and I remember trying AWS Lambda at that time. And that was it. For small side projects, it was overkill. I opted for a small VPS where I can run whatever I want. However, I understand why that’s not for everybody. Keeping a VPS up-to-date and secure requires some knowledge, but once properly set up, you make yourself your own little Netlify-like platform.
So what’s with serverless now? Simple — exploring a different technology, the ease of use, and the edge when talking about Cloudflare Workers particularly.
Let’s dive into the code. We’ll have this very simple API:
import { Hono } from 'hono';
const app = new Hono();
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' },
];
app.get('/api/users', (c) => {
return c.json({ users: users });
});
app.post('/api/users', async (c) => {
users.push({ id: 4, name: 'Dorian' });
return c.body(null, 201);
});
export default app;
We’re using Hono instead of writing vanilla code for Workers. We might explore the differences in some future posts, but the beauty of using Hono is that exporting the Hono application complies with Workers’ expected interface, which looks like this:
export default {
async fetch(request, env, ctx) {
// return standard Response object
}
};
Okay, now I understand that the following might be obvious to everybody, but I believe that being explicit might help someone better understand the caveats of serverless computing.
In our small application above, we have a shared array of users. You can get the list of users via GET /api/users and add a user (the same every time) to the shared list using POST /api/users. This is something that would work perfectly when deployed on a single server. But what happens when we deploy the code to Cloudflare Workers? We can do that using the wrangler CLI and this minimal wrangler.jsonc file:
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "workers-hono-api",
"main": "src/index.ts",
"compatibility_date": "2026-01-18"
}
Let’s deploy by running wrangler deploy. Within a few seconds, the app is deployed and ready.
So, what do we actually have now? Our code is deployed across Cloudflare’s edge network, but no compute resources are being consumed until a request arrives. Let’s call the API.
GET https://{your-workers-domain}/api/users
What happens is that Cloudflare spins up their V8-based workerd runtime and runs our code in it. The response is almost instantaneous (sure, we just return the array stored in memory) and contains our three users. What we just experienced is called a cold start, although it’s barely noticeable given Cloudflare’s approach and infrastructure.
Let’s add a user.
POST https://{your-workers-domain}/api/users
Now, our shared array should contain four users. So we can check using our GET endpoint again. You fetch the data and notice something weird. Sometimes you receive four users as expected, but sometimes there are still only three. If you decide to add another user via the POST endpoint again, you notice the behavior is even weirder — once you get the original array of users, then you get four users, then you get the expected five users. And it’s completely unpredictable.
This is the main caveat of serverless computing. The core thing to understand is that Worker instances do not share memory! Now combine it with this — at any given time, you cannot know whether the request you just fired toward your application hits the same Worker instance as before, some other already running Worker instance, or causes another Worker instance to spin up. Cloudflare’s infrastructure is fully in control here. And one more thing to realize — a Worker instance does not remain spun up forever. If there is no traffic for some time (again, you cannot know when), Cloudflare will just shut the instance down. Even during active use, Cloudflare can evict an instance’s memory and reinitialize it fresh. And once any of this happens, the instance loses its state. The state isn’t stored anywhere, nor is it transferred to other instances that might still be alive.
Therefore, some patterns you might be used to from more traditional computing models, like caching data in memory, won’t work reliably with Cloudflare Workers. Fortunately, Cloudflare (and other providers that offer some form of serverless computing) provides different kinds of solutions to this issue. You can use their distributed key-value store (Workers KV), serverless SQL database (D1), Durable Objects, or even object storage (R2) to store state and share it among Worker instances. Or you can run your own database anywhere and just connect to it from your Workers. It’s just important to understand that you should store your state outside the Worker instance memory (and in-memory caching won’t work reliably either — or, to be more precise, would be very unpredictable). We might explore the different solutions and their pros and cons in a future post.