Skip to main content
Platforms

Freestyle

Run Rivet workers on Freestyle.

Freestyle runs untrusted code in a sandboxed Deno runtime, which makes it a natural host for AI-generated backends. Workers run in serverless mode: the control plane calls your deployment to start actors.

Requirements

Steps

Add a Deno entrypoint

Freestyle serves web deployments with Deno, so the entrypoint hands requests to the registry handler.

import { registry } from "./index";

// Deno is provided by Freestyle's runtime.
// @ts-ignore
Deno.serve((request: Request) => registry.handler(request));

Deploy

const FREESTYLE_DOMAIN = "my-domain.style.dev";

const res = await freestyle.deployWeb(buildDir, {
  envVars: {
    FREESTYLE_ENDPOINT: `https://${FREESTYLE_DOMAIN}`,
    RIVETKIT_RUNTIME_MODE: "serverless",
    RIVET_ENDPOINT: "https://your-namespace:sk_...@api.rivet.dev",
  },
  timeout: 60 * 5,
  entrypoint: "server.ts",
  domains: [FREESTYLE_DOMAIN],
  build: false,
});
SettingWhy
timeoutMaximum request lifetime. Actors live inside a request, so keep this high. Five minutes is a reasonable floor.
entrypointThe file that starts the serverless handler
domainsYour Freestyle domain
build: falseSkip Freestyle’s build if you pre-build your assets

RIVETKIT_RUNTIME_MODE=serverless is required. Without it the app defaults to runner mode, which does not fit Freestyle’s request-driven model. See Freestyle’s web docs for buildDir and the other options.

Register the runner

Point the control plane at the deployment. requestLifespan must be shorter than Freestyle’s timeout, or the platform kills the request before actors migrate.

import { RivetClient } from "@rivetkit/engine-api-full";

const rivet = new RivetClient({
  environment: "https://api.rivet.dev",
  token: process.env.RIVET_API_TOKEN,
});

await rivet.runnerConfigsUpsert("freestyle-runner", {
  namespace: "my-rivet-namespace",
  datacenters: {
    default: {
      serverless: {
        url: `https://${FREESTYLE_DOMAIN}/api/rivet`,
        requestLifespan: 60 * 5 - 5,
        drainGracePeriod: 30,
        maxConcurrentActors: 1000,
      },
    },
  },
});
FieldMeaning
urlThe deployment’s /api/rivet base path. The control plane appends /start itself.
requestLifespanRequest lifetime, kept just under Freestyle’s timeout
drainGracePeriodTime reserved at the end of each request for actors to stop gracefully. Must be less than requestLifespan, and it defaults to 1800, so a short lifespan has to set it explicitly or the config is rejected.
maxConcurrentActorsCeiling on concurrent actors across the pool. Freestyle scales the deployment itself, so this is the only scaling bound to set.

Do not pin minRunners, maxRunners, slotsPerRunner, or runnersMargin. They are deprecated, and maxRunners still has a live effect: when maxConcurrentActors is omitted it becomes the concurrency ceiling, so maxRunners: 1 caps the whole deployment at one actor.

Verify

Once the runner config is applied, the deployment appears as connected in the dashboard.

Next steps