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.
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.
- Your app starts a worker. The worker connects out to the Runcoil server over HTTP/2 and registers its Tasks.
- A caller invokes a Task through the HTTP API.
- The server stores the new Run in PostgreSQL.
- The server pushes the Run to the worker on the open connection.
- 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
InvokeandReruncarries 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
- Run a Task on your machine in the Quickstart.
- Learn the vocabulary in Tasks and Runs.
- Learn why a handler can run again safely in Steps.