Skip to main content
Platforms

Render

Run the Rivet control plane on Render with managed PostgreSQL.

Requirements

Steps

Add the blueprint files

Three files at the root of your repository. The blueprint provisions a managed PostgreSQL database and the control plane together, and generates the admin token for you.

databases:
  - name: rivet-db
    plan: basic-256mb
    databaseName: rivet
    user: rivet

services:
  - type: web
    name: rivet-engine
    runtime: docker
    dockerfilePath: ./Dockerfile.render
    plan: starter
    healthCheckPath: /health
    envVars:
      - key: DATABASE_URL
        fromDatabase:
          name: rivet-db
          property: connectionString
      - key: RIVET__AUTH__ADMIN_TOKEN
        generateValue: true
FROM rivetdev/engine:latest

COPY entrypoint.render.sh /entrypoint.render.sh
RUN chmod +x /entrypoint.render.sh

ENTRYPOINT ["/entrypoint.render.sh"]

The entrypoint exists because Render hands you DATABASE_URL, and the engine reads RIVET__POSTGRES__URL. It translates one into the other.

#!/bin/sh

if [ -n "$DATABASE_URL" ]; then
    export RIVET__POSTGRES__URL="${DATABASE_URL}?sslmode=disable"
fi

exec /usr/bin/rivet-engine start

Commit and push all three.

Create the blueprint instance

  1. Open the Render dashboard.
  2. Click Blueprints, then New Blueprint Instance.
  3. Connect GitHub if you have not already, and select the repository.
  4. Click Apply.

Render creates the database and deploys the control plane.

Get the admin token

On the rivet-engine service, open the Environment tab, find RIVET__AUTH__ADMIN_TOKEN, and reveal it. You need it for the dashboard and for every worker.

Verify

Open your service URL with /ui/ appended:

https://rivet-engine-xxxx.onrender.com/ui/

Log in with the admin token.

Create the runner config

A runner config declares a pool that workers connect to. Without one the control plane refuses every worker, so create it before deploying any:

curl -X PUT "https://rivet-engine-xxxx.onrender.com/runner-configs/default?namespace=default" \
  -H "Authorization: Bearer $RIVET_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"datacenters":{"default":{"normal":{}}}}'

Use normal for long-lived workers. See Runner configs.

Connect a worker

RIVET_ENDPOINT=https://<namespace>:<admin-token>@rivet-engine-xxxx.onrender.com
RIVET_PUBLIC_ENDPOINT=https://<namespace>@rivet-engine-xxxx.onrender.com

Confirm the worker appears under Runners. See Workers.

WebSocket timeouts

Render’s proxy supports WebSockets but closes connections that sit idle past its own timeout. If you put your own reverse proxy in front of the engine on Render, raise its idle and read timeouts to 3600 seconds. See Ports.

Scaling past one instance

The blueprint above is a single instance on managed PostgreSQL, which is a fine starting point. Before scaling out, add NATS for pub/sub so instances coordinate. See Storage.

With NATS in place, instance count can be raised or handed to Render’s autoscaling on a CPU target. Target 60% CPU, matching the Kubernetes manifests, and keep a minimum of two instances. Autoscaling a control plane that is still on the file system backend corrupts it, but that does not apply here: this blueprint is on PostgreSQL from the start.

Next steps