Deploying Zero

To deploy a Zero app, you need to:

  1. Deploy your backend database. Most standard Postgres hosts work with Zero.
  2. Deploy zero-cache. We provide a Docker image that should work with any Docker host.
  3. Deploy your frontend. You can use any hosting service like Vercel or Netlify.

Scalability

😬`zero-cache` is Currently Single-Node

A single reasonably-sized zero-cache node can handle a fairly large number of users – thousands of concurrents or more depending on what they're doing.

But it's not infinitely scalable, and updating zero-cache today will take down your service for a minute or so while the Docker container restarts. We'll have this fixed soon.

Topology

While zero-cache is single-node, you should deploy it close to your database to minimize sync latency. In the future, you will be able to deploy zero-cache in multiple regions to provide low-latency access to users around the world.

Configuration

The zero-cache image is configured via environment variables. See zero-cache Config for available options.

Schema Deployment

zero-cache needs a copy of your zero-schema.json because it is used to enforce permissions.

You can deploy it as a plain file, using the ZERO_SCHEMA_FILE env var. For convenience, we also support putting the schema string itself directly in an env var, using ZERO_SCHEMA_JSON.

Example: Deploying to Fly.io

Let's deploy the Quickstart app to Fly.io. We'll use Fly.io for both the database and zero-cache.

Setup Quickstart

Go through the Quickstart guide to get the app running locally.

Setup Fly.io

Create an account on Fly.io and install the Fly CLI.

Create Postgres app

😬Warning
INITIALS=aa
PG_APP_NAME=$INITIALS-zstart-pg

PG_PASSWORD=$(dd if=/dev/urandom count=1 2> /dev/null | uuencode -m - | sed -ne 2p | cut -c-16)

fly postgres create \
  --name $PG_APP_NAME \
  --region lax \
  --initial-cluster-size 1 \
  --vm-size shared-cpu-2x \
  --volume-size 40 \
  --password=$PG_PASSWORD

Seed Upstream database

Populate the database with initial data and set its wal_level to logical to support replication to zero-cache. Then restart the database to apply the changes.

(cat ./docker/seed.sql; echo "\q") | fly pg connect -a $PG_APP_NAME
echo "ALTER SYSTEM SET wal_level = logical; \q" | fly pg connect -a $PG_APP_NAME
fly postgres restart --app $PG_APP_NAME

Create zero-cache Fly.io app

CACHE_APP_NAME=$INITIALS-zstart-cache
fly app create $CACHE_APP_NAME

Publish zero-cache

Create a fly.toml file. We'll copy the zero-schema.json into the toml file to pass it to the server as an environment variable.

CONNECTION_STRING="postgres://postgres:$PG_PASSWORD@$PG_APP_NAME.flycast:5432"

cat <<EOF > fly.toml
app = "$CACHE_APP_NAME"
primary_region = 'lax'

[build]
image = "registry.hub.docker.com/rocicorp/zero:canary"

[http_service]
internal_port = 4848
force_https = true
auto_stop_machines = 'off'
min_machines_running = 1

[[http_service.checks]]
grace_period = "10s"
interval = "30s"
method = "GET"
timeout = "5s"
path = "/"

[[vm]]
memory = '2gb'
cpu_kind = 'shared'
cpus = 2

[mounts]
source = "sqlite_db"
destination = "/data"

[env]
ZERO_REPLICA_FILE = "/data/sync-replica.db"
ZERO_UPSTREAM_DB="${CONNECTION_STRING}/zstart?sslmode=disable"
ZERO_CVR_DB="${CONNECTION_STRING}/zstart_cvr?sslmode=disable"
ZERO_CHANGE_DB="${CONNECTION_STRING}/zstart_cdb?sslmode=disable"
ZERO_JWT_SECRET="secretkey"
LOG_LEVEL = "debug"
ZERO_SCHEMA_JSON = """$(cat zero-schema.json)"""
EOF

Then publish zero-cache:

fly deploy

Use Remote zero-cache

cat <<EOF > .env
VITE_PUBLIC_SERVER='https://${CACHE_APP_NAME}.fly.dev/'
EOF

Now restart the frontend to pick up the env change, and refresh the app. You can stop your local database and zero-cache as we're not using them anymore. Open the web inspector to verify the app is talking to the remote zero-cache!

You can deploy the frontend to any standard hosting service like Vercel or Netlify, or even to Fly.io!

Deploy Frontend to Vercel

If you've followed the above guide and deployed zero-cache to fly, you can simply run:

vercel deploy --prod \
  -e ZERO_JWT_SECRET="secretkey" \
  -e VITE_PUBLIC_SERVER='https://${CACHE_APP_NAME}.fly.dev/'

to deploy your frontend to Vercel.

Explaining the arguments above --

  • ZERO_JWT_SECRET - The secret to create and verify JWTs. This is the same secret that was used when deploying zero-cache to fly.
  • VITE_PUBLIC_SERVER - The URL the frontend will call to talk to the zero-cache server. This is the URL of the fly app.

Example: $PLATFORM

Where should we deploy Zero next?? Let us know on Discord!