Skip to content

Introduction ​

Runcoil runs background Tasks for your application and keeps the state of every Run. It is a self-hosted server on PostgreSQL, plus a Go SDK.

Your code runs in your own application process. The server never runs it. Instead, a worker in your application connects out to the server, registers its Tasks, and waits for Runs. The server stores each Run and each Step outcome in PostgreSQL, so a restart or a failure does not lose the work.

Pre-release

The API and the schema may change before version 1.0.

How the pieces fit ​

Four parts take part in a Run. Press play, or step through the diagram.

How the pieces connect

Your app runs a worker. The worker connects out to the Runcoil server. A caller invokes a Task through the HTTP API, the server stores the Run in PostgreSQL, and then pushes the Run to the worker.

  1. Your app starts a worker. The worker connects out to the Runcoil server over HTTP/2 and registers its Tasks.
  2. A caller invokes a Task through the HTTP API.
  3. The server stores the new Run in PostgreSQL.
  4. The server pushes the Run to the worker on the open connection.
  5. The worker runs the handler and records each Step with the server, which stores it in PostgreSQL.
  • Your app contains a worker, built with the Go SDK. The worker holds your Task handlers.
  • The Runcoil server is a ConnectRPC API in front of PostgreSQL. It decides which worker gets which Run.
  • PostgreSQL holds Runs, Step outcomes, and schedules.
  • A caller invokes a Task through the server's HTTP API and reads the Run.

The worker opens the connection, so your application needs no inbound port.

What you get ​

  • Runs and Steps. A handler runs straight through. Each Step records its outcome before the handler continues. A retried Run replays the Steps that succeeded and does not run them again. See Steps.
  • Retries. A failed Step or Run is tried again with a delay. You set the policy per Task or per Step. See Retries.
  • Schedules. A Task can run on a cron expression, at an interval, or at times of day, in UTC. See Schedules.
  • Lost workers. A worker renews a lease on each Run it holds. If the worker dies, the lease expires and the Run goes to another worker.
  • Idempotent invokes. Every Invoke and Rerun carries an idempotency key. A repeat with the same key and input returns the first Run.
  • Rerun. A finished Run can run again from its start or from a chosen Step.

What it does not do ​

  • It does not run your code exactly once. A Step records its outcome after your function succeeds. If the process dies in between, the function can run again. Steps give durable progress, not transactions. See Steps.
  • It is pre-release. Only one server process is supported. The server uses one shared token and speaks plain HTTP, so put TLS in front of it.
  • It has no event triggers and no web interface yet.
  • It reads schedules in UTC only. A tick that passes while the server is down creates no Run.

Where to go next ​

Runcoil is pre-release. The API may change before 1.0.