A Python runtime for edge functions
It has been hard to ignore how much Python now runs in front of users. Teams who used to keep it behind an internal API are putting it straight onto the request path — scoring a recommendation, validating a webhook, rewriting a prompt before it ever reaches a model.
Until this week, that meant paying a cold-start tax measured in seconds. Today we're shipping the Kestrel Python runtime for edge functions, built around snapshot restore. Install the SDK with pip install kestrel, set KESTREL_TOKEN, and try the complete example below:
import asyncioimport kestrelfrom kestrel.edge import route, Response@route("/score")async def score(request): body = await request.json() model = kestrel.models.get("ranker-small") result = await model.predict( features=body["features"], timeout_ms=40, ) return Response.json({"score": result.value})if __name__ == "__main__": asyncio.run(kestrel.serve())Why cold starts hurt more in Python
A Node function starts in tens of milliseconds because most of what it needs is already compiled into the engine. A Python function imports. Every import numpy walks the file system, compiles bytecode and allocates objects before your handler has seen a byte of the request.
We measured the import phase across forty thousand production deployments. The median function spent 71% of its cold start importing modules it would need on every single request.
Snapshot, then restore
Instead of importing on every cold start, we import once — at build time — and freeze the interpreter's memory to disk.
The build runs your module top level, exactly as it would at boot
We pause the process and write a copy-on-write snapshot of its heap
On a cold start the edge maps that snapshot and resumes your handler
Anything that must be fresh per instance (random seeds, sockets) re-initialises through a
@on_restorehook
from kestrel.edge import on_restore
import random, httpx
client = None
@on_restore
def reconnect():
global client
random.seed()
client = httpx.AsyncClient(http2=True)A snapshot is only as safe as the state you let into it. If it holds a secret or a socket, it holds it for every instance that restores it.
What it costs, and what it doesn't
Before | With snapshots | |
|---|---|---|
p50 cold start | 1,840 ms | 96 ms |
p99 cold start | 4,210 ms | 310 ms |
Build time | 38 s | 44 s |
Image size | 112 MB | 131 MB |
The trade is a few seconds of build and some extra megabytes of storage for every function — which is the right direction to move cost, because builds happen once and cold starts happen to your users.
Try it
Snapshot restore is on by default for new Python projects on every plan. Existing projects can opt in with one line in kestrel.toml:
[functions.python]
snapshot = trueWe'd love to hear what you build with it.