Closed beta

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

Read the documentation

sarpius / hello-function
main · a7c42de
live
v41 serving while v42 builds zero downtime
  • Push received 0.3s
  • Build Node.js dependencies
  • v42 activated 24.8s
  • POST /hello 200 · 23ms
hello-function.sarpius.app Live in 24.8 seconds

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.

Step 01

Connect your repository

Choose GitHub, GitLab, Gitea, Bitbucket or any standard git remote. The function becomes part of your existing Project.

Step 02

Add function.json

Declare Node.js or Python, the entry file, memory tier and timeout. Keep the runtime contract with the code it describes.

Step 03

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.

hello-function / main Node.js
index.mjs handler(request)
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
    })
  };
}
function.json repository root
{
  "lang": "node",
  "tier": 128,
  "entry": "index.mjs",
  "timeout_s": 10
}
request 200 · application/json
$ 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.

HTTP

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.

POSTapi.example.com/api/hello?lang=en
methodpathquerybody
Cron

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.

15 8 * * 1-5
Europe/Amsterdam
At most once

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.

Compute
€0.000016
per GiB-second
Invocations
€0.20
per million invocations

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.

Within free allowance

Small API

€0.00/ month

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

Busy webhook

Five million calls

€4.20/ month

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

Longer workload

Two million calls

€6.60/ month

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.

Need the details? Read the Sarpius Functions documentation.

Closed beta

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.