Your functions are the boundary.
Clients call code you own. Every entry point — an HTTP call, a queue message, a cron schedule, a webhook, an agent's tool call — lands on the same committed handler, holding only what it declared.
One handler contract
The same request and response shape locally and hosted, whatever triggered it.
Capabilities, not credentials
A function reaches what it declares and nothing else — the blast radius is in the diff.
Background work included
Queues, schedules, and webhooks are declared beside the functions they run.
Functions, running
local developmentOne handler, every trigger
Write the behavior once and decide how it can be reached. An HTTP call from your app, a queue message, a cron schedule, an inbound webhook, and an agent's tool call all arrive at the same committed handler with the same request shape.
- Web-standard request and response objects, locally and hosted
- Background work shares the code path that serves requests
- Retries, dead letters, and timing are all testable on your machine
[[functions]]
name = "post-round"
entry = "post-round/index.ts"
auth = "required"
capabilities = ["db", "storage"]
[[queues]]
name = "new-rounds"
functions = ["notify"]Only the capabilities it declares
A function receives a scoped context as its second argument. The database, storage, push, secrets, and Signals appear only when the project says they should — so a reviewer can see a function's blast radius without reading its body.
- No ambient credentials for code to reach for
- An undeclared capability isn't restricted, it simply isn't there
- Capability changes show up in code review as a one-line diff
export default async function handler(req, capabilities) {
const user = capabilities.auth.user;
const { strokes } = await req.json();
capabilities.db.query(
"insert into rounds (user_id, strokes) values (?, ?)",
[user.id, strokes],
);
return new Response("ok");
}Built for real applications
What teams build with Functions.
Anything that needs a secret
A model, a payment provider, an email service. The key is declared for that one function, and the client never sees it.
Rules the client can't be trusted with
Applying a discount, awarding credits, moving money. The client asks; the function decides, validates, and writes.
Work that outlives the request
Enqueue it and answer immediately, or put it on a schedule — the same handler, reached a different way.
Committed functions give every client a clear, durable boundary around application behavior.
Why Snoozestack →