Workerkit's examples are a guided product tour, not a random pile of demos. Start with the smallest useful runtime, then move outward into managed loops, readiness, Opskit execution hooks, commands, execution policy, observability, Servekit presentation, and optional Workerkit-specific HTTP controls.
If you want the short directory index instead, use Workerkit Examples.
Run examples from the repository root. Most examples are runnable programs:
go run ./examples/<name>The test example is intentionally test-only:
go test ./examples/testingWhat it demonstrates: The smallest credible Workerkit program: New,
Register, StartAll, runtime and worker status, and Shutdown with one
custom Worker.
Run it:
go run ./examples/basicExpected output: The worker starts, the runtime reports running and
ready=true, the worker reports running, then shutdown stops the worker and
the runtime reports stopped.
What to notice: The worker owns only domain behavior. The runtime owns lifecycle, status, readiness aggregation, and graceful shutdown.
What this example intentionally does not show: Servekit, HTTP, commands, retry, observability, readiness warmup, or long-running loop cancellation.
What it demonstrates: NewLoopWorker as the managed alternative to an
unmanaged background goroutine.
Run it:
go run ./examples/loop-workerExpected output: The worker processes a few ticker batches, prints status while running, observes cancellation during shutdown, and exits cleanly.
What to notice: Workerkit owns lifecycle and cancellation. The loop owns
domain work and must observe ctx.Done().
What this example intentionally does not show: Manual goroutine ownership, commands, retry, Servekit, or HTTP.
What it demonstrates: Lifecycle and readiness are separate. A worker can be running before it is ready.
Run it:
go run ./examples/readinessExpected output: Initial status shows workers running but not all ready. After warmup, the readiness-contributing worker reports ready and aggregate runtime readiness changes.
What to notice: WorkerRuntime.SetReady(false) and
WorkerRuntime.SetReady(true) are worker-owned readiness signals.
WithWorkerReadinessContribution(false) keeps optional workers from deciding
aggregate readiness.
What this example intentionally does not show: Servekit /readyz, command
dispatch, retry policy, or HTTP operations routes.
What it demonstrates: Worker-owned domain commands without HTTP.
Run it:
go run ./examples/commandsExpected output: The example lists registered commands, dispatches JSON
payload bytes directly through Runtime.Dispatch, prints JSON result payload
bytes, then shows a command error recorded in worker status without failing the
worker lifecycle.
What to notice: Commands are transport-neutral. Workerkit routes and observes commands, but the worker owns payloads, result payloads, validation, and domain meaning.
What this example intentionally does not show: HTTP command dispatch, Servekit, retry, or lifecycle controls.
What it demonstrates: Workerkit periodically executing generic Opskit
Checker and CheckGroup hooks as managed workers.
Run it:
go run ./examples/opskit-checksExpected output: The single check and grouped checks run immediately, their observers print results, and the passive Opskit registry reports component and runtime state.
What to notice: Opskit defines the contracts and stores passive component inventory. Workerkit owns scheduling, timeout, cancellation, panic recovery, and readiness integration. Checked components are informational in the Opskit registry, and the group worker does not contribute to Workerkit readiness, so the database is not counted as a readiness gate multiple times.
What this example intentionally does not show: Servekit presentation, external dependencies, retry, or checks that ignore context cancellation.
What it demonstrates: Executing an opskit.CommandHandler through the
generic workerkit.CommandFromOpskit adapter.
Run it:
go run ./examples/opskit-commandExpected output: The example prints Opskit descriptor metadata discovered through Workerkit, then dispatches an Opskit command and prints its structured result as a JSON Workerkit payload.
What to notice: Opskit defines the command descriptor and handler hook but does not invoke it. Workerkit owns registration, admission, execution policy, and observation. No domain-specific Workerkit adapter is required.
What this example intentionally does not show: HTTP presentation, retries, or asynchronous accepted work.
What it demonstrates: Predicate-gated command retry with bounded attempts, exponential backoff, and full jitter.
Run it:
go run ./examples/retry-policyExpected output: A temporary command failure retries before succeeding. A permanent command failure stops without retry.
What to notice: retry.AttemptsIf receives max attempts, backoff, jitter,
and a retry predicate. The predicate decides which failures are safe to repeat.
Why this matters in production: Retries should be opt-in, bounded, jittered, and limited to failures that are actually temporary. Broad retry can amplify incidents or repeat unsafe side effects.
What this example intentionally does not show: HTTP, Servekit, lifecycle retry, or durable retries across process restarts.
What it demonstrates: Layered command backpressure with runtime-wide and worker-local command concurrency limits.
Run it:
go run ./examples/concurrency-limitsExpected output: Slow commands occupy command slots. Additional dispatches
are rejected with ErrRuntimeSaturated or ErrWorkerSaturated, and status
shows InFlight while work is active.
What to notice: A dispatch must pass both the runtime-wide gate and the worker-local gate.
Why this matters in production: Runtime limits protect the service boundary. Worker-local limits protect one worker from being overwhelmed by expensive commands.
What this example intentionally does not show: HTTP saturation mapping, Servekit, retry, or lifecycle controls.
What it demonstrates: How worker failures affect aggregate runtime status.
Run it:
go run ./examples/failure-policyExpected output: Three labeled scenarios show
FailurePolicyIsolate, FailurePolicyMarkRuntimeUnready, and
FailurePolicyFailRuntime, followed by runtime and worker status.
What to notice: A worker failure can be isolated, force readiness down, or move aggregate runtime state to failed depending on policy.
Why this matters in production: Not every worker has the same importance. Failure policy lets optional and critical workers communicate different service-level impact.
What this example intentionally does not show: Servekit readiness, HTTP, retry, or command routing.
What it demonstrates: One runtime as a service boundary containing
ingest, index, and maintenance workers.
Run it:
go run ./examples/multi-workerExpected output: Workers start in registration order, status lists each worker independently, commands route to different workers, and shutdown stops the runtime.
What to notice: A runtime gives multiple workers shared lifecycle and aggregate readiness while preserving independent worker inspection and command routing.
What this example intentionally does not show: Servekit, HTTP operations, retry policy, or observability adapters.
What it demonstrates: Workerkit core can be tested directly without HTTP, Servekit, Kubernetes, or external infrastructure.
Run it:
go test ./examples/testingExpected output: Go test output should pass for examples/testing.
What to notice: Tests can create a runtime, register a fake worker, dispatch commands directly, assert status and readiness, and attach a custom observer.
What this example intentionally does not show: HTTP boundary tests, Servekit integration, or external telemetry infrastructure.
What it demonstrates: Backend-neutral Workerkit observer events mapped into
structured slog records.
Run it:
go run ./examples/observability-slogExpected output: JSON-style log records for lifecycle transitions, readiness changes, command success, command failure, and background worker failure.
What to notice: Observability is core-runtime behavior. Servekit is not required for worker lifecycle, command, readiness, or failure events.
What this example intentionally does not show: HTTP request logs, OpenTelemetry, or an external log backend.
What it demonstrates: Workerkit observer events flowing into the first-party OpenTelemetry adapter.
Run it:
go run ./examples/observability-otelExpected output: Local stdout-style provider output for command spans, span events, command retry failure, counters, and histograms.
What to notice: Dispatch IDs belong on spans and events, not metric labels. The example stays copyable without requiring an external OpenTelemetry collector or telemetry backend.
What this example intentionally does not show: Servekit, HTTP tracing, a real collector, or production OpenTelemetry exporter setup.
What it demonstrates: The flagship Kit Series composition in one copyable service skeleton.
Run it:
go run ./examples/production-compositionArchitecture overview: One Workerkit runtime contains ingest, index,
and maintenance workers. Workerkit owns worker lifecycle, readiness,
commands, retry, concurrency, failure policy, and slog observer events.
Opskit carries the component/readiness/inspection contract. Servekit owns HTTP
serving, app routes, readiness endpoints, endpoint policy, and shutdown.
Routes:
GET /app/statusGET /app/search?q=...GET /readyzGET /admin/componentsGET /admin/components/catalog_service
Curl commands:
curl -i http://localhost:8080/app/status
curl -i http://localhost:8080/readyz
curl -s -H 'X-Ops-Token: dev-secret' http://localhost:8080/admin/components
curl -s -H 'X-Ops-Token: dev-secret' http://localhost:8080/admin/components/catalog_serviceExpected output: Workers warm up, structured logs describe runtime and
worker events, app routes return service state, and generic Servekit admin
routes expose Workerkit inspection through Opskit. Missing or wrong
X-Ops-Token values return 401 for component inspection.
What to notice: This is the full boundary story. Workerkit owns worker semantics; Opskit owns the shared operational registry contract; Servekit owns HTTP and service semantics. Workerkit-specific HTTP controls are not part of the flagship composition.
In Kubernetes, these routes are pod-local. /admin/components/catalog_service
shows the runtime in the pod that handled the request.
Security note: The development token gate is a placeholder. Production
deployments must use real authentication, authorization, audit logging, request
limits, route-specific timeouts, and network exposure policy for the /admin
operations surface.
What this example intentionally does not show: External infrastructure, durable queues, durable workflow state, a real auth system, or a production OpenTelemetry backend.
The following examples are intentionally outside the primary composition progression. Use them when operators need command dispatch or privileged lifecycle controls. Generic readiness still flows from the Opskit registry into Servekit.
What it demonstrates: Opt-in HTTP command dispatch through opshttp.
Run it:
go run ./examples/opshttp-commandsRoutes:
POST /admin/commands/dispatchGET /readyz
Curl commands:
# 200: successful dispatch
curl -i -X POST http://localhost:8080/admin/commands/dispatch \
-H 'Content-Type: application/json' \
-H 'X-Ops-Token: dev-secret' \
-d '{"worker":"cache","name":"cache/put","payload":{"key":"homepage","value":"warm"}}'
# 400: invalid request
curl -i -X POST http://localhost:8080/admin/commands/dispatch \
-H 'Content-Type: application/json' \
-H 'X-Ops-Token: dev-secret' \
-d '{"worker":"","name":"cache/put"}'
# 404: missing worker
curl -i -X POST http://localhost:8080/admin/commands/dispatch \
-H 'Content-Type: application/json' \
-H 'X-Ops-Token: dev-secret' \
-d '{"worker":"missing","name":"cache/put"}'
# 404: missing command
curl -i -X POST http://localhost:8080/admin/commands/dispatch \
-H 'Content-Type: application/json' \
-H 'X-Ops-Token: dev-secret' \
-d '{"worker":"cache","name":"cache/missing"}'
# 429: saturation; run the slow command in one terminal,
# then run the second command in another terminal before it finishes
curl -i -X POST http://localhost:8080/admin/commands/dispatch \
-H 'Content-Type: application/json' \
-H 'X-Ops-Token: dev-secret' \
-d '{"worker":"cache","name":"cache/slow","payload":{"sleepMillis":5000}}'
curl -i -X POST http://localhost:8080/admin/commands/dispatch \
-H 'Content-Type: application/json' \
-H 'X-Ops-Token: dev-secret' \
-d '{"worker":"cache","name":"cache/put","payload":{"key":"homepage","value":"warm"}}'Expected output: Successful dispatch returns 200 with the command result.
Invalid requests return 400, missing workers and commands return 404, and
worker saturation returns 429 through opshttp.
What to notice: Core Workerkit commands stay transport-neutral. opshttp
adapts command dispatch to HTTP and WithDispatchOptions applies dispatch-only
endpoint policy.
Security note: Command dispatch is mutating and intentionally opt-in. This
example uses a development-only X-Ops-Token gate and timeout to show where
real authentication, authorization, and audit policy belong. No passive status
or inspection routes are added by opshttp.
What this example intentionally does not show: Admin lifecycle controls or production-grade authz.
What it demonstrates: Privileged Workerkit lifecycle controls exposed
through Servekit-backed opshttp.
Run it:
go run ./examples/admin-lifecycleRoutes:
POST /admin/workers/startPOST /admin/workers/drainPOST /admin/workers/stopPOST /admin/runtime/startPOST /admin/runtime/drainPOST /admin/runtime/stopGET /readyz
Curl commands:
curl -i http://localhost:8080/readyz
curl -i -X POST http://localhost:8080/admin/workers/start \
-H 'Content-Type: application/json' \
-H 'X-Admin-Token: dev-secret' \
-d '{"name":"ingest"}'
curl -i -X POST http://localhost:8080/admin/runtime/start \
-H 'X-Admin-Token: dev-secret'
curl -i -X POST http://localhost:8080/admin/runtime/drain \
-H 'X-Admin-Token: dev-secret'Expected output: Startup output explains that workers are registered but not
running. /readyz may fail until workers are started through lifecycle routes.
Authorized admin operations requests return 200; missing or wrong tokens
return 401. Lifecycle requests print audit logs and worker start/stop
messages.
What to notice: This example intentionally does not call
runtime.StartAll before serving. The lifecycle routes are the point of the
example.
Security note: The /admin operations surface exposes privileged lifecycle
controls. Do not expose it publicly. Protect it with real
authentication, authorization, audit logging, request limits, and route-specific
timeouts.
What this example intentionally does not show: Normal application routes, command dispatch, or production authz.