BTick Scheduler Service
BTick is a generic API-driven scheduler service for recurring HTTP jobs.
It provides:
- Scheduler API (
cmd/scheduler-api):
- JSON API under
/api/v1
- server-rendered UI with
templ + templui + tailwindcss + htmx
- API key management and API key auth
- Scheduler Worker (
cmd/scheduler-worker):
- Postgres polling for due jobs
- safe multi-worker claim semantics
- HTTP execution with retries and run history persistence
- execution through
task-orchestration
Architecture
- Control plane: API service
- Execution plane: Worker service
- Source of truth: Postgres (
jobs, job_runs, api_keys)
- Scheduling model: persisted
next_run_at + cron expression
- No in-memory timer dependence
Required Libraries
Project Layout
cmd/
scheduler-api/
scheduler-worker/
internal/
apikeys/
auth/
authorization/
config/
db/
handlers/
errors/
v1/
httpserver/
jobs/
runs/
scheduler/
worker/
migrations/
queries/
sdk/
go/
scheduler/
views/
Environment Variables
Shared:
API:
PORT (default 8080)
STATIC_ASSETS_PATH (default ./assets)
UI_SESSION_SECRET (default dev-session-secret-change-me)
UI_SESSION_TTL_HOURS (default 12)
Worker:
WORKER_ID (default scheduler-worker-1)
WORKER_CONCURRENCY (default 4)
WORKER_POLL_INTERVAL_MS (default 2000)
WORKER_STALE_CLAIM_MINUTES (default 5)
WORKER_MAX_CLAIMS_PER_TICK (default 20)
WORKER_TASK_LOG_PATH (default ./logs/tasks)
WORKER_TASK_STATE_DB_PATH (default ./data/task_orchestration.db)
WORKER_HTTP_TIMEOUT_SECONDS (default 90)
Run Locally
- Set
DATABASE_URL.
- Start API:
go run ./cmd/scheduler-api
- Start worker:
go run ./cmd/scheduler-worker
Migrations run automatically on startup.
Run with Docker Compose
Build and run Postgres + API + worker:
docker compose up --build
Services:
- Scheduler API:
http://localhost:8080
- Scheduler Worker: separate container (
scheduler-worker)
- Adminer:
http://localhost:8010
- Postgres:
localhost:5432 (btick / btick / btick)
Notes:
- Both API and worker run migrations on startup.
- Update
UI_SESSION_SECRET in compose.yml before production use.
Build Container Images
Build API image:
docker build -f Dockerfile.api -t btick-scheduler-api:local .
Build worker image:
docker build -f Dockerfile.worker -t btick-scheduler-worker:local .
API Endpoints
Health:
GET /api/v1/health
GET /healthz
GET /readyz
Jobs:
POST /api/v1/jobs
GET /api/v1/jobs
GET /api/v1/jobs/{jobId}
PATCH /api/v1/jobs/{jobId}
DELETE /api/v1/jobs/{jobId}
POST /api/v1/jobs/{jobId}/pause
POST /api/v1/jobs/{jobId}/resume
POST /api/v1/jobs/{jobId}/trigger
Runs:
GET /api/v1/jobs/{jobId}/runs
GET /api/v1/runs/{runId}
API Keys:
POST /api/v1/api-keys
GET /api/v1/api-keys
POST /api/v1/api-keys/{keyId}/revoke
Authentication
Protected API endpoints expect:
Authorization: Bearer <api-key>
Keys are generated once and only key_prefix + secure hash are stored.
UI Routes
/register
/login
/ui/jobs
/ui/jobs/new
/ui/jobs/{jobId}
/ui/jobs/{jobId}/edit
/ui/jobs/{jobId}/runs
/ui/runs/{runId}
/ui/api-keys
/ui/api-keys/new
SDK
Go SDK lives at:
See sdk/go/scheduler/README.md for examples.
SQLC + Migrations
- SQL schema migration files:
migrations/
- Query contracts:
queries/
- SQLC config:
sqlc.yaml
- Query implementation package:
internal/db/sqlc