Community content. Review instructions before giving them to an AI agent — treat modules like open-source code.
Serverless Conventions
Write serverless and edge functions that perform well and cost predictably: stateless handlers, cold-start budgets, timeout and memory sizing, idempotency for retries, database connection pooling, local dev parity, and cost awareness.
Mby @markdownersPublished August 21, 2026 · ~3 min read
0 downloads · Used by 0 stacks
A serverless function can be frozen, discarded, or run concurrently in dozens of isolated instances at any moment — never store state in memory between invocations, and never assume the process that handled the last request is the one handling this one.
Stateless handlers
- Treat every invocation as if it's the first one on a brand-new instance — no in-memory cache, counter, or connection can be assumed to survive between requests, because the platform is free to spin up a new instance per request under load.
- Persist anything that must survive across invocations (session state, counters, rate-limit windows) in an external store (database, Redis, KV), never in module-level variables assumed to persist.
- Keep handlers pure with respect to global state: given the same input and same external state, the handler should behave the same regardless of which instance or how many concurrent instances are running it.
Cold-start budget
- Keep the deployed bundle small and dependency count low — bundle size is one of the biggest levers on cold-start time, and an unnecessarily large dependency tree (a full ORM for one query, an entire SDK for one endpoint) is dead weight on every cold start.
- Do expensive one-time setup (parsing config, creating a client) at module scope, outside the handler function, so it happens once per cold start and is reused across warm invocations — but never rely on it having run recently.
- Avoid heavy synchronous work during initialization (large JSON parses, synchronous file reads) that blocks the first request on a cold instance — lazy-initialize anything not needed for every request.
Timeout and memory sizing
- Set the function timeout deliberately based on the slowest expected legitimate request, not the platform default — a timeout that's too generous lets a hung dependency burn cost and delay error surfacing; one that's too tight kills legitimate slow requests.
- Size memory based on actual profiling, not a guess — on most platforms memory allocation also scales CPU, so under-provisioning silently makes the function slower as well as more memory-constrained, and over-provisioning wastes cost linearly.
Idempotency for retries
- Assume the platform may retry an invocation that times out or errors after partially completing (this is common on queue-triggered and scheduled functions) — write handlers so a retried invocation with the same input doesn't double-charge, double-send, or double-write.
- Use the same idempotency-key pattern as background jobs (a dedup check on a natural or supplied key) for any serverless function with an external side effect.
Database connections
- Never open a fresh database connection per invocation without pooling — serverless concurrency can spike to hundreds of simultaneous instances, each opening its own connection, and this exhausts a traditional database's connection limit almost immediately.
- Use an external connection pooler (e.g. a pooling proxy sitting between functions and the database) or a database designed for serverless concurrency (HTTP-based drivers, built-in pooling) rather than the database's native connection protocol directly from every instance.
- Reuse a connection across warm invocations by creating it at module scope, but always handle the case where a warm connection has gone stale (the platform froze the instance and the connection timed out server-side) and reconnect rather than erroring out.
Local dev parity
- Run functions locally through the platform's actual emulator/CLI rather than a plain Node script that imports the handler — routing, environment variable injection, and request/response shape differ enough between "just calling the function" and the real invocation path that skipping this hides real bugs until deploy.
- Keep environment variables and secrets configuration identical in shape between local and deployed environments, differing only in values, so a config-shape bug isn't discovered for the first time in production.
Cost awareness
- Remember that serverless cost scales with both invocation count and duration — an accidental infinite retry loop or a function invoked in a hot per-item loop can produce a cost spike far faster than a fixed-capacity server would.
- Set concurrency limits and budget alerts explicitly rather than relying on "it'll be fine" — the same elasticity that makes serverless convenient also makes runaway cost possible with no manual step required.
Badge
Link back to this module from your own README.
[](https://markdowners.com/m/markdowners/serverless-conventions)Discussions about this module
No discussions about this module yet.
Start a discussion
Comments (0)
Sign in to comment. Sign in
No comments yet. Be the first to add one.