Jadpo is experimental and not ready for production. These docs follow the compiler's main branch as of 5 Nov 2026. What's built · Install 0.3.0
jadpo
Guides: all 21

Guides

Deploy to Cloudflare Workers

You end with the app built as a Worker, reaching its database through Hyperdrive.

On this page

jadpo build can build your app as WebAssembly for Cloudflare Workers, with the JavaScript that loads it and the description Wrangler, Cloudflare's command-line tool, deploys. This guide builds a book catalogue as a Worker that reaches its PostgreSQL database through Hyperdrive.

You need:

  • A Cloudflare account. Check Cloudflare's pricing for which plan includes Workers and Hyperdrive.
  • Wrangler. It needs Node.js; run it with npx wrangler, which fetches it the first time. npx wrangler login opens your browser to sign in to Cloudflare.
  • A PostgreSQL database reachable from the internet, such as one from a hosted PostgreSQL provider. One on your own machine won't do, since Cloudflare can't reach it.

You start from an app with a Book entity and routes that add a book and read one back. Build an API shows how to write those.

Say what to build

The database's address is a setting, so it isn't written in your code. config { } and PostgresUrl, a standard type, are built into Jadpo, and the name database_url is yours.

config.jadpo:

jadpo
config {    /// The PostgreSQL database the app keeps its data in.    database_url: PostgresUrl}

app.jadpo names the database and the program to build. main and limits are names you choose for its two connections, and web is a name you choose for the program. Driver, Target and rate_limits: are built in.

app.jadpo:

jadpo
application {    connections: {        main: {            driver: Driver.postgres            url: config.database_url        }        limits: {            driver: Driver.cloudflare_rate_limits            namespace: 1001        }    }    rate_limits: {        store: limits    }    deployables: {        web: {            serves: [main]            target: Target.wasm        }    }}
  • The main connection is your database, read through the database_url setting.
  • deployables: lists the programs the app is built into. Without it there is one, app, built as a server program. web is built for Workers, Target.wasm, and serves: [main] means it answers the API's routes.
  • Every route is rate-limited. A server program counts requests in its own memory, but a Worker runs in many places at once, so the counts are kept by Cloudflare's rate-limiting binding, through the limits connection. namespace: 1001 is a number you choose; Cloudflare needs an id for each limit, and Jadpo numbers them from this one.
  • An app that sends email or has subscribers or schedules also says the Worker runs them: runs: [Trigger.subscribers, Trigger.schedules].

Build it

shell
jadpo build
output
  worker: build/target/web/wrangler.json  module: build/target/web/web.wasm  size: 7.2 MB, 2.7 MB gzipped  database: DATABASE_URL through Hyperdrive, no id  build: b_0ccbb5029fcf  serves: main  commit: none  settings: DATABASE_URLalert: `DATABASE_URL` has no Hyperdrive id: create one with caching off and build with it in `JADPO_HYPERDRIVE_DATABASE_URL`alert: Built from files git doesn't track: no commit explains its eventsbuilt: web, wasm in 61.7 snext: jadpo migrate apply  it starts only once its database has every migration

build/target/web/ now holds the Worker: the WebAssembly module, the JavaScript that loads it, and wrangler.json. It names the Worker after your project's folder and lists the two limits Jadpo counts, numbered from your namespace:. A secret setting with no default would be listed there too, as one the Worker needs.

Connect the database through Hyperdrive

A Worker keeps no connection to your database open between requests, and opening one for each request is slow. Hyperdrive is Cloudflare's service that keeps connections open and hands one to each request. Create one for your database with caching off, since a cache could answer a read with data that has since changed. Keep the database's address in a file only you can read, such as ~/books-app.env, holding DATABASE_URL=<your database's address>, and load it from there so it isn't typed into your shell:

shell
(set -a; . ~/books-app.env; npx wrangler hyperdrive create books \  --connection-string="$DATABASE_URL" --caching-disabled)

Wrangler prints the new Hyperdrive's id. Build again with it:

shell
JADPO_HYPERDRIVE_DATABASE_URL=<the id Wrangler printed> jadpo build

Deploy

Apply the migrations to the database first:

shell
(set -a; . ~/books-app.env; jadpo migrate apply)

A hosted provider's address often ends in settings such as ?sslmode=require. Remove them: Jadpo refuses an address that sets TLS itself, since its connection decides, and it always uses TLS to a database on another machine. Use the provider's direct address, not its pooled one.

Then deploy from the Worker's folder:

shell
cd build/target/webnpx wrangler deploy

On Workers, settings are the Worker's variables and secrets, which Cloudflare keeps. Store a secret with npx wrangler secret put <NAME>, which asks for the value at a prompt, and give other settings as --var NAME:value to npx wrangler deploy. Any setting with no default: is listed as a secret the Worker needs, even one that isn't secret, so store it with secret put too. Wrangler prints the Worker's address, which answers the same routes and health check as the server program.

Read more

A Workers deployable, Declared deployables and Rate limits on Workers.

Markdown for agents: /guides/guide-deploy-to-workers.md.Built from Jadpo main at aee2e8f. Jadpo's CI compiles this guide's code and runs its tests.