# 2.1.0: Go SDK 1.0

2026-03-10 · https://galley.themes.dev/changelog/v2-1-go-sdk/

> The Go SDK leaves beta with a stable API, generics for payloads and workflow steps. Plus trace context that follows a run from enqueue to worker.

## Go SDK 1.0

`github.example/runnel/runnel-go` is now 1.0, and we will keep its API stable until 2.0. Since the beta in November it has run more than 400 million runs for 60 teams, and their feedback shaped most of what changed.

- Payloads are typed with generics, so `runnel.NewJob("send-invoice", fn)` infers the payload type from `fn` and `Enqueue` checks it at compile time.
- Workflows are in: `runnel.NewWorkflow`, `runnel.Step` and `runnel.Sleep` work as they do in TypeScript and Python.
- The worker shuts down cleanly on `SIGTERM`, finishing running attempts for up to 30 seconds before it exits.
- Go 1.22 is now the minimum.

```go
sendInvoice := runnel.NewJob("send-invoice", func(ctx runnel.Context, p Invoice) error {
	return mailer.Send(ctx, p.ID)
}, runnel.WithRetries(5, runnel.Exponential))
```

## Trace context

All three SDKs now pass W3C trace context from the code that enqueues a run to the worker that runs it. If you use OpenTelemetry, a run shows up as a child span of the request that created it.

## Fixes

- The Python worker no longer logs a warning when a job returns `None`.
- `runnel runs list --json` printed times in local time. It now prints UTC, like the API.
