Production checklist

What to decide before Weir takes real traffic, and what a first week should look like.

This page is the operator's runbook, rendered from the repository so it cannot drift. The full document, including multi-node Valkey deployment, is docs/runbook.md.

Before the first deployment

  1. Set GOMEMLIMIT (plain library use; the caddy binary derives its own limit, see 7.5). The default memory store takes 40% of it, clamped to 16 MiB to 8 GiB. Without it the store takes 256 MiB and New logs a warning. Weir does not look at cgroup limits for you.
  2. List what the origin reads from the request. Strict forwarding sends the origin only keyed, allowed and required headers (README, "Strict forwarding"). An Accept-Language, device header or cookie that is not in Key.Headers, Key.Cookies or Forward.Allow is invisible to the origin, so a page built from it comes out wrong, and the same wrong page is cached.
  3. Run with the defaults for a day and read the warnings. The log line weir: cookies stripped from cacheable requests (Info, once, after the first 5 minutes of Bypass.ReportStrippedCookies) lists cookie names the origin never saw. A name you recognize as session or login state belongs in Bypass.Cookies (those requests skip the cache) or in Key.Cookies (each value is its own entry).
  4. Decide what happens to requests with Authorization or a session cookie. A response to a request with Authorization is stored only when it carries public, a valid s-maxage or must-revalidate (FR-STO-5), and those requests are never coalesced with other users' requests.
  5. Put a rate limiter in front for distinct-path floods (06 R-2). Weir bounds origin concurrency; it does not rate-limit clients.
  6. Decide the stale policy. Defaults serve stale only inside the origin's stale-while-revalidate and stale-if-error windows. Setting Freshness.DefaultStaleIfError is the usual first change; it trades freshness for survival of an outage (D6).

Alerts worth having

  • The breaker is open for more than a few minutes (weir_breaker_state == 2).
  • weir_shed_total is nonzero for more than a minute: the origin cannot keep up, or MaxConcurrent is set too low for it.
  • weir_stale_served_total{reason="sie"} or reason="circuit-open" is rising: you are serving through an outage.
  • weir_store_errors_total is rising (remote stores only).
  • Hit ratio falls by half against the same hour last week.

Planned operations

  • Warm start: Engine.Warm(ctx, requests, origin) fetches a list of requests at background priority (4 at a time, never using the foreground reserve) and skips keys that are already fresh. It returns counts of fetched, skipped, not-stored and failed. Run it after a deploy that empties the cache, from a goroutine that you own.
  • Shutdown: stop the server first (srv.Shutdown), then Engine.Close(ctx). Close cancels background work after the grace period in ctx, and requests that arrive later get weir.ErrClosed (503).
  • Config changes: weir.New rejects an invalid Config with ErrInvalidConfig, naming the field. A running engine's config is fixed; build a new engine and swap it at your handler.

Toolchain

Build with Go 1.27.2 or later. Earlier 1.27 releases carry standard library vulnerabilities in HTTP/2, net/textproto and crypto/tls that govulncheck reports against the code paths weirhttp uses. The minimum the module accepts is Go 1.27.0, and CI tests the two latest Go releases.

Settings to leave alone until you have a reason

The defaults are chosen so that a mistake fails toward the origin doing more work, never toward a user seeing someone else's response. The settings that reverse one of those choices are on the tuning page, each with what you give up.