Serverless functions
Ship a function. Skip the server.
Connect a repository and every push builds a new Node.js or Python version. Each active invocation runs inside its own Firecracker microVM boundary, with snapshot-based starts and no shared application container.
- About 25 seconds from push to live
- Previous version stays live on failure
- Push received 0.3s
- Build Node.js dependencies
- v42 activated 24.8s
- POST /hello 200 · 23ms
How it works
Three steps, then every push is live.
Functions use the same git-first flow as the rest of Sarpius, but deploy into isolated microVMs built for short-lived work.
Connect your repository
Choose GitHub, GitLab, Gitea, Bitbucket or any standard git remote. The function becomes part of your existing Project.
Add function.json
Declare Node.js or Python, the entry file, memory tier and timeout. Keep the runtime contract with the code it describes.
Push and route
A push builds a new immutable version. When it is ready, Sarpius switches traffic without downtime and leaves the previous version in place if the build fails.
- GitHub
- GitLab
- Gitea
- Bitbucket
- + generic remote
See it in action
A handler, a small manifest, a live URL.
The request object carries the HTTP method, path, query, headers and body. Return a status, string headers and a body.
export async function handler(request) {
const input = request.body
? JSON.parse(request.body)
: {};
return {
status: 200,
headers: {
"content-type": "application/json"
},
body: JSON.stringify({
message: `Hello, ${input.name ?? "world"}`,
method: request.method,
path: request.path
})
};
}{
"lang": "node",
"tier": 128,
"entry": "index.mjs",
"timeout_s": 10
}$ curl -X POST \
-H "content-type: application/json" \
-d '{"name":"Ada"}' \
https://hello-function.sarpius.app/hello
{"message":"Hello, Ada","method":"POST","path":"/hello"}Functionality
A first-class part of your Project.
Functions sit beside your components, databases and buckets. The console keeps deployment, traffic and cost in one place.
Git to live
Every push to the configured branch starts a build. Current production measurements put a successful version live in about 25 seconds.
Atomic version switch
The active version changes only after the new build succeeds. Existing traffic keeps reaching the previous version until activation.
Project native
Functions get their own Project sidebar section and share routing and members with the rest of the app.
A plain request object
Each invocation receives the method, routed path, raw query, filtered headers and a UTF-8 body, and returns a status, string headers and a body.
Logs and latency
Read build logs, recent invocations and hourly request and error counts. The console tracks p50 and p95 invocation latency.
Wallet and hard caps
Usage comes from the same wallet as the rest of Sarpius. Set a monthly EUR limit for one function or the whole Project.
Triggers
Answer a request or run on schedule.
Both trigger types use the same active version, budget checks, usage meter and microVM isolation.
A URL that belongs to your Project
Use a free *.sarpius.app subdomain or mount the function on a Project route such as /api/hello. Method, path, query, headers and body reach the handler.
Scheduled work without a worker
Use a standard five-field cron expression and an IANA timezone. Add up to 10 schedules to one function for reports, cleanup and recurring integrations.
A claimed slot is never retried after a crash. Missed slots are not caught up later, so side effects cannot run twice because of scheduler recovery.
Pricing
Pay only for the work that runs.
Compute is measured in GiB-seconds, then invocation count is added. The monthly free allowance is applied first, across the wallet-backed bill.
Every month, before paid usage
100,000 GiB-seconds and 1,000,000 invocations are free. Charges are billed in whole cents, rounded down, and any remainder stays in your usage until it adds up to a cent. There is no minimum charge.
Small API
128 MiB, 200 ms average, 1,000,000 invocations
128/1024 × 0.2 × 1,000,000 = 25,000 GiB-s
25,000 is below 100,000 free; 1,000,000 calls are free → €0.00
Five million calls
128 MiB, 500 ms average, 5,000,000 invocations
128/1024 × 0.5 × 5,000,000 = 312,500 GiB-s
(312,500 - 100,000) × €0.000016 = €3.40 compute
(5,000,000 - 1,000,000) / 1,000,000 × €0.20 = €0.80 calls → €4.20
Two million calls
256 MiB, 1 second average, 2,000,000 invocations
256/1024 × 1 × 2,000,000 = 500,000 GiB-s
(500,000 - 100,000) × €0.000016 = €6.40 compute
(2,000,000 - 1,000,000) / 1,000,000 × €0.20 = €0.20 calls → €6.60
Charges are debited from your existing Sarpius wallet. Billing applies the monthly free allowance first. A monthly cap can be set per function and per Project, and its safety check uses gross usage before free credits, so it can stop earlier than the final invoice. When a cap is reached or billing blocks the function because the wallet is empty, new HTTP requests receive 402 Payment Required and no microVM is acquired.
Guardrails
The useful part is what the runtime refuses.
These limits are enforced by the service. They are not soft guidance in a dashboard.
A microVM boundary
Every active invocation gets a Firecracker microVM boundary instead of a shared application container. Warm VMs can be reused sequentially for the same function version, never concurrently across tenants.
Fixed memory tiers
Choose 128, 256 or 512 MiB in function.json. The tier is enforced for the microVM and is also the basis for GiB-second metering.
60 seconds maximum
A manifest can set a timeout from 1 to 60 seconds. A timeout returns 504 and destroys the VM instead of putting an uncertain instance back into the warm pool.
Infrastructure fails closed
If the platform database, usage writer or host egress guard cannot prove it is ready, the service returns 503 and does not run customer code for free or outside policy.
The budget is a hard stop
A reached function cap, Project cap or billing block returns HTTP 402 before a VM is acquired. The request does not continue and create more spend.
Cron is at most once
The scheduler records a slot before dispatch. A crash can leave one run abandoned, but that slot is never replayed after side effects may already have happened.
FAQ
Questions before the first push.
How quickly does a new version go live?
Current production measurements are about 25 seconds from push to active version. Build time still depends on the repository and dependencies. The previous version keeps answering until the new one activates.
What happens when a build fails?
Activation happens only after a successful build. A failed build is shown in the Project with its log, while the last active version stays live.
Do two customers ever share a function container?
No shared application container runs customer functions. Each active invocation gets a Firecracker microVM boundary. A warm VM may be paused and reused later for the same function version, with its clock refreshed before the next call.
Which runtimes are available?
Node.js and Python are available in the closed beta. The manifest uses lang: "node" or lang: "python", with an exported or defined handler(request).
What does a function receive from an HTTP trigger?
The handler receives the method, routed path, raw query, filtered headers and UTF-8 body. It returns an HTTP status, string header values and a response body.
What happens at the spending limit?
The service returns HTTP 402 before acquiring a microVM. The same response is used when billing has blocked the function because the wallet cannot cover further usage.
Push the function. Keep the Project.
Deploy serverless work beside the code, data, routes and people it belongs with. Pay for real execution, and stop automatically at the limit you set.