Back to README · API Endpoints →
Developer guide for building, running, testing, and operating wait0.
- Go
1.22+ - GNU Make
- Optional: Docker (for containerized local runs)
make devThe development setup uses fixed local-only credentials:
- API bearer token:
demotoken - Dashboard Basic Auth:
admin/admin
Never use the debug configuration in production.
Equivalent direct command:
go run ./cmd/wait0 -config ./debug/wait0.yamlThe direct command uses the same demotoken API credential. The dashboard is enabled automatically by make dev; when using the direct command, set both dashboard credential environment variables to admin.
make buildOutput binary: bin/wait0.
| Command | What it does | Expected result |
|---|---|---|
make test |
Runs unit tests | Exit 0 on success |
make test-race |
Runs tests with race detector | Exit 0 and no race reports |
make lint |
Runs go vet ./... |
No vet issues |
make coverage |
Runs coverage gate for internal/wait0 |
Coverage >= configured threshold |
make ci-check |
Full local quality gate (lint + test + test-race + coverage + build) |
Exit 0 when release-ready |
make fmt |
Runs go fmt ./... |
Source files formatted |
make help |
Lists all targets | Human-readable command list |
Coverage threshold default: 80% (COVERAGE_THRESHOLD in Makefile).
| Flag | Type | Default | Description |
|---|---|---|---|
-config |
string | /wait0.yaml (or WAIT0_CONFIG) |
Path to YAML config file |
| Variable | Default | Description |
|---|---|---|
WAIT0_CONFIG |
/wait0.yaml |
Default value for -config |
WAIT0_INVALIDATE_DISK_CACHE_ON_START |
true |
If true, LevelDB cache directory is cleared on process start |
WAIT0_SEND_REVALIDATE_MARKERS |
true |
Controls sending revalidation marker headers during background revalidation |
WAIT0_DASHBOARD_USERNAME |
unset | Basic Auth username for GET /wait0/dashboard and dashboard API routes |
WAIT0_DASHBOARD_PASSWORD |
unset | Basic Auth password for GET /wait0/dashboard and dashboard API routes |
WAIT0_DASHBOARD_RATE_LIMIT_RPM |
120 |
Per-IP fixed-window rate limit for /wait0/dashboard* routes |
WAIT0_DASHBOARD_TRUST_PROXY_HEADERS |
false |
If true, dashboard rate limiter client IP extraction trusts X-Forwarded-For (first hop) |
WAIT0_DASHBOARD_TRUSTED_PROXY_CIDRS |
unset | Comma-separated CIDRs of trusted proxy source IPs allowed to supply X-Forwarded-For |
| Field | Type | Required | Notes |
|---|---|---|---|
storage.ram.max |
size string | yes | RAM budget (example: 100m) |
storage.disk.max |
size string | yes | Disk budget (example: 1g) |
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
server.port |
int | no | 8080 |
Listener port |
server.origin |
URL string | yes | - | Origin base URL (trailing slash trimmed) |
| Field | Type | Default | Notes |
|---|---|---|---|
enabled |
bool | false |
Enables POST /wait0/invalidate |
queue_size |
int | 128 |
Buffered async queue size |
worker_concurrency |
int | 4 |
Number of invalidation workers |
max_body_bytes |
int | 1048576 |
Max request body size |
max_paths_per_request |
int | 1024 |
Paths soft/hard cap |
max_tags_per_request |
int | 1024 |
Tags soft/hard cap |
hard_limits |
bool | false |
When true, oversized path/tag arrays return 400 |
Validation rules: all numeric values above must be > 0.
| Field | Required | Notes |
|---|---|---|
id |
yes | Unique token ID |
token or token_env |
yes | token_env is resolved at startup |
scopes[] |
yes | At least one scope, deduplicated |
For invalidation API, at least one token must have scope invalidation:write when invalidation is enabled.
For stats API (GET /wait0), tokens need scope stats:read.
For dashboard:
stats:readtoken is required to enable dashboard routes.invalidation:writetoken is optional; without it, dashboard is stats-only and invalidate action is disabled.- Built-in dashboard rate limiting exists (
WAIT0_DASHBOARD_RATE_LIMIT_RPM), but for internet-exposed deployments reverse-proxy/WAF rate limiting is still mandatory. - Pre-auth rate-limit key is
client IPonly. - Post-auth rate-limit key is
(client IP, verified auth principal). - With trusted proxies enabled,
client IPusesX-Forwarded-Forfirst hop only whenRemoteAddrbelongs toWAIT0_DASHBOARD_TRUSTED_PROXY_CIDRS.
| Field | Required | Notes |
|---|---|---|
match |
yes | Supports PathPrefix(...) with optional ` |
priority |
no | Rules are sorted ascending by priority |
bypass |
no | For matching paths, bypass cache completely |
bypassWhenCookies[] |
no | If any listed cookie exists, bypass cache |
bypassWhenRequestHeaders[] |
no | If any listed request header is present, bypass cache; matching is case-insensitive and empty values count |
cachableContentType[] |
no | Exact cache-eligible media types; defaults to text/html and application/xhtml+xml; parameters are ignored |
varyByQueryParams[] |
no | Query params that should participate in cache identity for matching paths |
expiration |
no | Duration for stale check and async revalidation |
warmUp.pauseBetweenRuns |
with warmUp |
Pause after a complete loop before loading the next URL snapshot; must be > 0; 10s is recommended for fast full-capacity reruns |
warmUp.runEvery |
deprecated | Legacy alias for pauseBetweenRuns; logs a replacement warning and uses the new pause-after-completion behavior |
warmUp.maxRequestsAtATime |
with warmUp |
Must be > 0 |
warmupRequestHeaderPresets |
no | Map of header names to non-empty value arrays; requires warmUp and expands their Cartesian product on every loop |
| Field | Type | Notes |
|---|---|---|
sitemaps[] |
URL list | Enables sitemap discovery loop |
initialDelay |
duration | Initial wait before first discovery |
initalDelay |
duration | Legacy typo still supported |
rediscoverEvery |
duration | Periodic rediscovery interval (> 0) |
| Field | Type | Notes |
|---|---|---|
debug_headers |
string array | Diagnostic headers to emit; omitted enables all eight supported headers, while an explicit [] disables all |
log_stats_every |
duration | Enables periodic stats logging (> 0) |
log_warmup |
bool | Emits warmup batch summaries |
log_url_autodiscover |
bool | Emits per-sitemap discovery logs |
log_revalidation_every |
duration | Deprecated alias; enables warmup logging |
- Cache key is path-only by default (
/a/b). - Rule field
varyByQueryParams[]opt-ins selected query params so/a/b?page,/a/b?page=1, and/a/bcan be distinct cache entries. - Query params not listed in
varyByQueryParams[]and all fragments are ignored for cache identity. - Only
GETrequests are cache-eligible. - Bypassed and non-
GETrequests are sent upstream asGETwithout the original body. bypassWhenRequestHeadersskips lookup and storage when any configured header is present; use it for headers such asAuthorizationthat make a response unsafe to share.- Non-2xx origin responses are not cached and existing cached key is removed.
- Origin responses whose media type is not in
cachableContentTypeare served but not stored; background revalidation deletes an existing entry if its new media type is disallowed. - Keep static assets in CDN, Nginx, and browser caches; wait0 defaults to caching only dynamic HTML/XHTML SWR responses.
- Origin
2xxresponses withCache-Control: no-cacheorno-storeare not stored; either directive received during revalidation deletes the existing entry. - Warmup loops never overlap: wait0 completes the current rule snapshot, waits
pauseBetweenRuns, then loads a fresh snapshot. - Variant warmup replays the original URL with the referenced request headers saved on each discovered concrete response.
warmupRequestHeaderPresetsadds its full Cartesian product and can substantially increase cache entries and origin traffic. Cache-Variantexpressions may reference every request header, including cookies and authorization. Referenced values are persisted for later refresh, so protecting sensitive values is the operator's responsibility.logging.debug_headersmay select any ofX-Wait0,X-Wait0-Reason,X-Wait0-Revalidated-At,X-Wait0-Revalidated-By,X-Wait0-Discovered-By,X-Wait0-Revalidate-At,X-Wait0-Revalidate-Entropy, andX-Wait0-Cache-Variant-Key.- Omit
logging.debug_headersto enable all diagnostics; setdebug_headers: []to disable all of them. X-Wait0response header identifies behavior (hit,miss,bypass,ignore-by-cookie,ignore-by-request-header,ignore-by-status,bad-gateway).X-Wait0-Reasonidentifies why a response was bypassed or failed (for example,bypass-ruleornon-cacheable-content-type).
- API Endpoints — auth, schemas, status codes, and examples.
- Cache variant complexity — root manifests, subkeys, warmup, and family operations.
- README — product overview and quick start.