<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>bouine</title><link>https://bouine.org/v0.4/</link><description>Recent content on bouine</description><generator>Hugo</generator><language>en</language><lastBuildDate>Mon, 16 Feb 2026 16:31:38 +0100</lastBuildDate><atom:link href="https://bouine.org/v0.4/index.xml" rel="self" type="application/rss+xml"/><item><title>Install</title><link>https://bouine.org/v0.4/docs/getting-started/install/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/getting-started/install/</guid><description>&lt;h2 id="docker"&gt;Docker&lt;/h2&gt;
&lt;p&gt;The fastest way to run bouine is the Docker image:&lt;/p&gt;



&lt;div class="expressive-code"&gt;
 &lt;figure class="frame is-terminal not-content"&gt;
 &lt;figcaption class="header"&gt;
 &lt;span class="title"&gt;&lt;/span&gt;
 &lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker pull bouinecache/bouine:latest
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker run --rm -p 8080:80 -p 9000:9000 bouinecache/bouine:latest&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;The default image includes a minimal config at &lt;code&gt;/etc/bouine/config.yaml&lt;/code&gt; so the container starts without a volume mount.&lt;/p&gt;</description></item><item><title>Lifecycle</title><link>https://bouine.org/v0.4/docs/operations/lifecycle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/operations/lifecycle/</guid><description>&lt;h2 id="starting-bouine"&gt;Starting bouine&lt;/h2&gt;



&lt;div class="expressive-code"&gt;
 &lt;figure class="frame is-terminal not-content"&gt;
 &lt;figcaption class="header"&gt;
 &lt;span class="title"&gt;&lt;/span&gt;
 &lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bouine serve --config /etc/bouine/config.yaml --log-format json&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;On Kubernetes the StatefulSet container runs this command via the Helm
chart (see &lt;code&gt;deploy/helm/bouine/templates/statefulset.yaml&lt;/code&gt;). The
&lt;code&gt;--log-format json&lt;/code&gt; flag ensures structured logging for aggregation.&lt;/p&gt;</description></item><item><title>Migration from NGINX</title><link>https://bouine.org/v0.4/docs/guides/nginx-migration/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/guides/nginx-migration/</guid><description>&lt;h2 id="directive-mapping"&gt;Directive mapping&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;NGINX directive&lt;/th&gt;
 &lt;th&gt;bouine config&lt;/th&gt;
 &lt;th&gt;Notes&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;proxy_cache_path ... max_size=1g&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;storage.hot_max_bytes: 1GiB&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;bouine uses in-RAM storage, no filesystem levels&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;proxy_cache_path ... keys_zone=api:10m&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Not needed&lt;/td&gt;
 &lt;td&gt;bouine manages shard count automatically (&lt;code&gt;N=NumCPU&lt;/code&gt;)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;proxy_cache_valid 200 60s&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;routes[].cache.ttl_default: 60s&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Per-route, respects &lt;code&gt;Cache-Control&lt;/code&gt; by default&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;proxy_cache_valid 404 10s&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;routes[].cache.negative_ttl: 10s&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Negative caching for error responses&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;proxy_cache_use_stale error http_500 http_502 http_503 http_504&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;routes[].cache.stale_if_error: 30s&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Serves stale on origin 5xx or timeout&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;proxy_cache_background_update on&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;routes[].cache.stale_while_revalidate: 10s&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Background revalidation while serving stale&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;proxy_cache_revalidate on&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Built-in&lt;/td&gt;
 &lt;td&gt;Conditional requests (&lt;code&gt;If-None-Match&lt;/code&gt;, &lt;code&gt;If-Modified-Since&lt;/code&gt;)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;proxy_cache_key $scheme$host$request_uri&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Automatic&lt;/td&gt;
 &lt;td&gt;xxhash128 of scheme+host+path+sorted query&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;proxy_cache_key $scheme$host$request_uri$http_accept&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;cache.key.include_headers: [Accept]&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Explicit header keying&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;proxy_ignore_headers Vary&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;cache.key.include_headers: [...]&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Explicit header keying instead of Vary&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;proxy_no_cache $variable&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;routes[].cache.enabled: false&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Per-route disable&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;proxy_cache_bypass $variable&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Not needed&lt;/td&gt;
 &lt;td&gt;Use route matching to separate cached/uncached&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;proxy_cache_lock on&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Built-in (request collapsing)&lt;/td&gt;
 &lt;td&gt;Single-flight per cache key&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;proxy_cache_lock_timeout 5s&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Built-in&lt;/td&gt;
 &lt;td&gt;Subscribers wait for leader fetch&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;proxy_cache_min_uses 3&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Not needed&lt;/td&gt;
 &lt;td&gt;bouine caches on first response (RFC 9111)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;add_header X-Cache-Status $upstream_cache_status&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Built-in&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;X-Cache&lt;/code&gt; header (HIT, MISS, STALE, BYPASS, REVALIDATED)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;proxy_next_upstream error timeout&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;upstream_pools[].health.passive&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Passive health checks with outlier ejection&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="key-differences"&gt;Key differences&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No zone configuration&lt;/strong&gt; — bouine manages memory automatically with SIEVE eviction&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No filesystem cache&lt;/strong&gt; — bouine uses in-RAM hot tier + mmap warm tier (no &lt;code&gt;proxy_cache_path&lt;/code&gt; on disk)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Clustering built-in&lt;/strong&gt; — NGINX requires third-party modules for cache sharing; bouine has gossip + peer fetch&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RFC 9111 native&lt;/strong&gt; — bouine implements the spec directly, not via directives&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Observability built-in&lt;/strong&gt; — Prometheus &lt;code&gt;/metrics&lt;/code&gt;, structured JSON access logs with &lt;code&gt;cache_status&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No &lt;code&gt;proxy_pass&lt;/code&gt; needed&lt;/strong&gt; — upstream pools are declared separately and referenced by name in routes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Declarative config&lt;/strong&gt; — no &lt;code&gt;if&lt;/code&gt; blocks, no &lt;code&gt;map&lt;/code&gt; directives, no embedded Lua&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="example-api-gateway"&gt;Example: API gateway&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;NGINX:&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Authentication</title><link>https://bouine.org/v0.4/docs/operations/authentication/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/operations/authentication/</guid><description>&lt;p&gt;All write endpoints require &lt;code&gt;Authorization: Bearer &amp;lt;token&amp;gt;&lt;/code&gt;. The token is resolved in priority order:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;BOUINE_ADMIN_TOKEN&lt;/code&gt; environment variable&lt;/strong&gt; (recommended for Kubernetes / Vault injection)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;admin.token&lt;/code&gt; in the config file&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Auto-generated&lt;/strong&gt; random token (logged as &lt;code&gt;WARN&lt;/code&gt; at startup)&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="environment-variable"&gt;Environment variable&lt;/h3&gt;
&lt;p&gt;Set &lt;code&gt;BOUINE_ADMIN_TOKEN&lt;/code&gt; to inject the token without baking it into the config ConfigMap:&lt;/p&gt;</description></item><item><title>Cache policy</title><link>https://bouine.org/v0.4/docs/configuration/cache-policy/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/configuration/cache-policy/</guid><description>&lt;h2 id="ttl-selection"&gt;TTL selection&lt;/h2&gt;
&lt;p&gt;bouine picks freshness in this order:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;CDN-Cache-Control&lt;/code&gt; (RFC 9211 targeted header — overrides &lt;code&gt;Cache-Control&lt;/code&gt; for shared caches)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;s-maxage&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;max-age&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Expires&lt;/code&gt; (valid dates only; syntactically invalid Expires values are ignored)&lt;/li&gt;
&lt;li&gt;Route &lt;code&gt;ttl_default&lt;/code&gt; (operator fallback when origin sends no freshness)&lt;/li&gt;
&lt;li&gt;Heuristic freshness from &lt;code&gt;Last-Modified&lt;/code&gt; (10% of &lt;code&gt;Date − Last-Modified&lt;/code&gt;, where allowed by status code)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If the route has &lt;code&gt;ttl_override&lt;/code&gt; set, its value &lt;strong&gt;replaces&lt;/strong&gt; the result of
this waterfall entirely. See 

&lt;a class="link link--text" href="https://bouine.org/v0.4/docs/configuration/cache-policy/#ttl-override"&gt;TTL override&lt;/a&gt; below.&lt;/p&gt;</description></item><item><title>Codebase guide</title><link>https://bouine.org/v0.4/docs/contributing/codebase/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/contributing/codebase/</guid><description>&lt;h2 id="package-map"&gt;Package map&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Package&lt;/th&gt;
 &lt;th style="text-align: right"&gt;Layer&lt;/th&gt;
 &lt;th&gt;Purpose&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;internal/server&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;L1&lt;/td&gt;
 &lt;td&gt;HTTP/1.1, TLS, route matching&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;internal/storage&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;L2&lt;/td&gt;
 &lt;td&gt;Hot store, warm tier, WAL, SIEVE&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;internal/cache&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;L3&lt;/td&gt;
 &lt;td&gt;RFC 9111 state machine and handler&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;internal/origin&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;L4&lt;/td&gt;
 &lt;td&gt;Upstream pools, health checks, hedged transport&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;internal/cluster&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;L5&lt;/td&gt;
 &lt;td&gt;memberlist gossip, hash ring, peer fetch&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;internal/admin&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;L6&lt;/td&gt;
 &lt;td&gt;Admin HTTP API&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;internal/observability&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: right"&gt;L7&lt;/td&gt;
 &lt;td&gt;Metrics, logs, access log&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;| &lt;code&gt;pkg/api&lt;/code&gt; | public | Wire types shared by SDK and admin |
| &lt;code&gt;pkg/bouineapi&lt;/code&gt; | public | Go SDK |&lt;/p&gt;</description></item><item><title>Migration from Varnish</title><link>https://bouine.org/v0.4/docs/guides/varnish-migration/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/guides/varnish-migration/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Status:&lt;/strong&gt; Stable for production use. Assumes familiarity with VCL and bouine&amp;rsquo;s YAML configuration model.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="quick-reference"&gt;Quick reference&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Varnish concept&lt;/th&gt;
 &lt;th&gt;bouine equivalent&lt;/th&gt;
 &lt;th&gt;Notes&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;VCL subroutines&lt;/td&gt;
 &lt;td&gt;declarative YAML config&lt;/td&gt;
 &lt;td&gt;bouine uses config, not code&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;vcl_recv&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;routes[].match&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;routing and request matching&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;vcl_hash&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;automatic cache key (&lt;code&gt;xxhash64&lt;/code&gt;)&lt;/td&gt;
 &lt;td&gt;scheme + host + path + query + method&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;vcl_backend_fetch&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;upstream_pools[]&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;backend pool config&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;vcl_backend_response&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;origin &lt;code&gt;Cache-Control&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;bouine honors RFC 9111 strictly&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;beresp.ttl&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;cache.ttl_default&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;overridden by origin headers&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;beresp.grace&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;cache.stale_while_revalidate&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;SWR semantics&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;ban()&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;admin API &lt;code&gt;POST /v1/ban&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;HTTP-based invalidation API&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;purge&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;admin API &lt;code&gt;POST /v1/purge&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;exact-match invalidation&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Varnish log (&lt;code&gt;-g request&lt;/code&gt;)&lt;/td&gt;
 &lt;td&gt;structured JSON logs (stdout)&lt;/td&gt;
 &lt;td&gt;pipe to any log aggregator&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;varnishstat&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;/metrics&lt;/code&gt; (Prometheus)&lt;/td&gt;
 &lt;td&gt;Prometheus-compatible metrics&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;VSM/shared memory&lt;/td&gt;
 &lt;td&gt;in-process memory&lt;/td&gt;
 &lt;td&gt;no mmap, no VSM files&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="1-conceptual-mapping"&gt;1. Conceptual mapping&lt;/h2&gt;
&lt;h3 id="the-big-picture"&gt;The big picture&lt;/h3&gt;
&lt;p&gt;Varnish is a &lt;strong&gt;programmable cache&lt;/strong&gt; — you write VCL to define cache behavior.
bouine is a &lt;strong&gt;declarative cache&lt;/strong&gt; — you write YAML to describe routes, backends,
and cache policies, and bouine implements RFC 9111 rigorously.&lt;/p&gt;</description></item><item><title>Quick start</title><link>https://bouine.org/v0.4/docs/getting-started/first-cache/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/getting-started/first-cache/</guid><description>&lt;p&gt;Start a tiny origin server:&lt;/p&gt;



&lt;div class="expressive-code"&gt;
 &lt;figure class="frame is-terminal not-content"&gt;
 &lt;figcaption class="header"&gt;
 &lt;span class="title"&gt;&lt;/span&gt;
 &lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mkdir -p /tmp/bouine-origin
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8be9fd;font-style:italic"&gt;printf&lt;/span&gt; &lt;span style="color:#f1fa8c"&gt;&amp;#39;hello from origin\n&amp;#39;&lt;/span&gt; &amp;gt; /tmp/bouine-origin/index.html
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;python3 -m http.server &lt;span style="color:#bd93f9"&gt;3000&lt;/span&gt; --directory /tmp/bouine-origin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;Create &lt;code&gt;config.yaml&lt;/code&gt;:&lt;/p&gt;



&lt;div class="expressive-code"&gt;
 &lt;figure class="frame not-content"&gt;
 &lt;figcaption class="header"&gt;
 &lt;span class="title"&gt;&lt;/span&gt;
 &lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff79c6"&gt;listen&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;http&lt;/span&gt;: &lt;span style="color:#f1fa8c"&gt;&amp;#34;:8080&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;admin&lt;/span&gt;: &lt;span style="color:#f1fa8c"&gt;&amp;#34;:9000&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff79c6"&gt;storage&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;hot_max_bytes&lt;/span&gt;: 256Mo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff79c6"&gt;upstream_pools&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ff79c6"&gt;name&lt;/span&gt;: origin
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;targets&lt;/span&gt;: [&lt;span style="color:#f1fa8c"&gt;&amp;#34;127.0.0.1:3000&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff79c6"&gt;routes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ff79c6"&gt;match&lt;/span&gt;: { &lt;span style="color:#ff79c6"&gt;path_prefix&lt;/span&gt;: / }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;pool&lt;/span&gt;: origin
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;cache&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;ttl_default&lt;/span&gt;: 60s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;stale_while_revalidate&lt;/span&gt;: 10s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;stale_if_error&lt;/span&gt;: 300s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;Run bouine:&lt;/p&gt;</description></item><item><title>Reverse proxy examples</title><link>https://bouine.org/v0.4/docs/guides/reverse-proxies/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/guides/reverse-proxies/</guid><description>&lt;h2 id="bouine-in-front-of-caddy"&gt;bouine in front of Caddy&lt;/h2&gt;
&lt;p&gt;Caddy typically serves static files or acts as a reverse proxy itself. Deploy bouine in front of Caddy to add caching without modifying Caddy&amp;rsquo;s config.&lt;/p&gt;</description></item><item><title>Cache invalidation</title><link>https://bouine.org/v0.4/docs/operations/cache-invalidation/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/operations/cache-invalidation/</guid><description>&lt;h2 id="purge-exact-url"&gt;Purge (exact URL)&lt;/h2&gt;



&lt;div class="expressive-code"&gt;
 &lt;figure class="frame is-terminal not-content"&gt;
 &lt;figcaption class="header"&gt;
 &lt;span class="title"&gt;&lt;/span&gt;
 &lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6272a4"&gt;# CLI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bouine purge https://example.com/products/123 --token &amp;lt;token&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6272a4"&gt;# API&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -X POST http://127.0.0.1:9000/v1/purge &lt;span style="color:#f1fa8c"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -H &lt;span style="color:#f1fa8c"&gt;&amp;#34;Authorization: Bearer &amp;lt;token&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#f1fa8c"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -H &lt;span style="color:#f1fa8c"&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; &lt;span style="color:#f1fa8c"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -d &lt;span style="color:#f1fa8c"&gt;&amp;#39;{&amp;#34;url&amp;#34;:&amp;#34;https://example.com/products/123&amp;#34;}&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;In a cluster, the purge is forwarded to all live peers via HTTP fan-out (in &lt;code&gt;strong&lt;/code&gt; mode) or gossiped via the memberlist broadcast queue (in &lt;code&gt;eventual&lt;/code&gt; mode).&lt;/p&gt;</description></item><item><title>Cluster consistency modes</title><link>https://bouine.org/v0.4/docs/operations/cluster-modes/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/operations/cluster-modes/</guid><description>&lt;h2 id="verify-your-mode"&gt;Verify your mode&lt;/h2&gt;



&lt;div class="expressive-code"&gt;
 &lt;figure class="frame is-terminal not-content"&gt;
 &lt;figcaption class="header"&gt;
 &lt;span class="title"&gt;&lt;/span&gt;
 &lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6272a4"&gt;# Prometheus metric: always 1 with the mode label.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -s http://127.0.0.1:9000/metrics | grep bouine_cluster_mode_info
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6272a4"&gt;# Admin API: /v1/cluster/peers returns all members in every mode.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -s http://127.0.0.1:9000/v1/cluster/peers &lt;span style="color:#f1fa8c"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -H &lt;span style="color:#f1fa8c"&gt;&amp;#34;Authorization: Bearer &lt;/span&gt;&lt;span style="color:#f1fa8c"&gt;${&lt;/span&gt;&lt;span style="color:#8be9fd;font-style:italic"&gt;BOUINE_ADMIN_TOKEN&lt;/span&gt;&lt;span style="color:#f1fa8c"&gt;}&lt;/span&gt;&lt;span style="color:#f1fa8c"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6272a4"&gt;# CLI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bouine cluster peers --server 127.0.0.1:9000 --token &lt;span style="color:#f1fa8c"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#f1fa8c"&gt;${&lt;/span&gt;&lt;span style="color:#8be9fd;font-style:italic"&gt;BOUINE_ADMIN_TOKEN&lt;/span&gt;&lt;span style="color:#f1fa8c"&gt;}&lt;/span&gt;&lt;span style="color:#f1fa8c"&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;Expected: every node reports the same &lt;code&gt;mode&lt;/code&gt; label. If they disagree, the cluster
has a configuration drift — every pod must use the same mode.&lt;/p&gt;</description></item><item><title>Docker</title><link>https://bouine.org/v0.4/docs/getting-started/docker/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/getting-started/docker/</guid><description>&lt;h2 id="run-the-official-image"&gt;Run the official image&lt;/h2&gt;



&lt;div class="expressive-code"&gt;
 &lt;figure class="frame is-terminal not-content"&gt;
 &lt;figcaption class="header"&gt;
 &lt;span class="title"&gt;&lt;/span&gt;
 &lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker run --rm &lt;span style="color:#f1fa8c"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -p 8080:80 &lt;span style="color:#f1fa8c"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -p 9000:9000 &lt;span style="color:#f1fa8c"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; bouinecache/bouine:latest&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/figure&gt;
&lt;/div&gt;
&lt;h2 id="mount-a-config-file"&gt;Mount a config file&lt;/h2&gt;



&lt;div class="expressive-code"&gt;
 &lt;figure class="frame is-terminal not-content"&gt;
 &lt;figcaption class="header"&gt;
 &lt;span class="title"&gt;&lt;/span&gt;
 &lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker run --rm &lt;span style="color:#f1fa8c"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -p 8080:80 &lt;span style="color:#f1fa8c"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -p 9000:9000 &lt;span style="color:#f1fa8c"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -v &lt;span style="color:#f1fa8c"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#8be9fd;font-style:italic"&gt;$PWD&lt;/span&gt;&lt;span style="color:#f1fa8c"&gt;/config.yaml:/etc/bouine/config.yaml:ro&amp;#34;&lt;/span&gt; &lt;span style="color:#f1fa8c"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; bouinecache/bouine:latest&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/figure&gt;
&lt;/div&gt;
&lt;h2 id="build-locally"&gt;Build locally&lt;/h2&gt;
&lt;p&gt;On Apple Silicon targeting a Linux amd64 cluster:&lt;/p&gt;</description></item><item><title>Security</title><link>https://bouine.org/v0.4/docs/contributing/security/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/contributing/security/</guid><description>&lt;p&gt;Report security issues via GitHub&amp;rsquo;s


&lt;a class="link link--text" href="https://github.com/bouine-cache/bouine/security/advisories/new" rel="external"&gt;Private vulnerability reporting&lt;/a&gt;
— it creates a tracked, embargoed advisory. No security email alias is
published.&lt;/p&gt;
&lt;h2 id="scope"&gt;Scope&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;bouine binary&lt;/li&gt;
&lt;li&gt;Helm chart&lt;/li&gt;
&lt;li&gt;Container image&lt;/li&gt;
&lt;li&gt;Go SDK&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="examples-of-high-impact-issues"&gt;Examples of high-impact issues&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Cache poisoning that leaks one user&amp;rsquo;s response to another&lt;/li&gt;
&lt;li&gt;HTTP request smuggling through the data plane&lt;/li&gt;
&lt;li&gt;Admin API authentication bypass&lt;/li&gt;
&lt;li&gt;Peer impersonation in cluster mode&lt;/li&gt;
&lt;li&gt;Path traversal in warm-tier storage&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="hardening-checklist"&gt;Hardening checklist&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Keep admin port private; expose only through internal network or mTLS.&lt;/li&gt;
&lt;li&gt;Use TLS verification for upstreams.&lt;/li&gt;
&lt;li&gt;Run containers as non-root.&lt;/li&gt;
&lt;li&gt;Use NetworkPolicy for cluster and admin ports.&lt;/li&gt;
&lt;li&gt;Monitor purge/ban rates for misuse.&lt;/li&gt;
&lt;li&gt;Do not log request/response bodies or credentials.&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Static file serving</title><link>https://bouine.org/v0.4/docs/configuration/static-files/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/configuration/static-files/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;A route can serve files from a local directory instead of proxying to an
upstream pool. This eliminates the need for a separate origin server (nginx,
Caddy) when the content is already on the same machine as bouine — useful
for single-node CDN edges, sidecar deployments, and static asset routes.&lt;/p&gt;</description></item><item><title>Storage tiers</title><link>https://bouine.org/v0.4/docs/configuration/storage/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/configuration/storage/</guid><description>&lt;p&gt;bouine uses a two-tier storage architecture: a fast in-memory &lt;strong&gt;hot tier&lt;/strong&gt; and an optional disk-backed &lt;strong&gt;warm tier&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="hot-tier-ram"&gt;Hot tier (RAM)&lt;/h2&gt;
&lt;p&gt;The primary cache store. Every cache hit is served from here.&lt;/p&gt;</description></item><item><title>Capacity planning</title><link>https://bouine.org/v0.4/docs/guides/capacity-planning/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/guides/capacity-planning/</guid><description>&lt;h2 id="step-1-estimate-your-working-set"&gt;Step 1: Estimate your working set&lt;/h2&gt;
&lt;p&gt;The &lt;strong&gt;working set&lt;/strong&gt; is the total size of responses that need to stay cached for acceptable hit rates.&lt;/p&gt;



&lt;div class="expressive-code"&gt;
 &lt;figure class="frame not-content"&gt;
 &lt;figcaption class="header"&gt;
 &lt;span class="title"&gt;&lt;/span&gt;
 &lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;working_set ≈ unique_cacheable_urls × avg_response_size&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/figure&gt;
&lt;/div&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Workload&lt;/th&gt;
 &lt;th&gt;Typical working set&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;REST API (100k endpoints, 2 KiB avg)&lt;/td&gt;
 &lt;td&gt;~200 MiB&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;E-commerce catalog (1M products, 5 KiB avg)&lt;/td&gt;
 &lt;td&gt;~5 GiB&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Static site / CDN (50k assets, 50 KiB avg)&lt;/td&gt;
 &lt;td&gt;~2.5 GiB&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Media-heavy site (10k pages, 200 KiB avg)&lt;/td&gt;
 &lt;td&gt;~2 GiB&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;If you cannot estimate, start with 2 GiB and monitor &lt;code&gt;bouine_hot_store_bytes / bouine_hot_store_max_bytes&lt;/code&gt;. If it stays above 0.9 consistently, double &lt;code&gt;hot_max_bytes&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Kubernetes</title><link>https://bouine.org/v0.4/docs/getting-started/kubernetes/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/getting-started/kubernetes/</guid><description>&lt;h2 id="add-the-chart-repository"&gt;Add the chart repository&lt;/h2&gt;
&lt;p&gt;bouine publishes a Helm chart repository at &lt;strong&gt;&lt;code&gt;https://charts.bouine.org&lt;/code&gt;&lt;/strong&gt;,
indexed on 

&lt;a class="link link--text" href="https://artifacthub.io/packages/search?repo=bouine" rel="external"&gt;Artifact Hub&lt;/a&gt;.
The chart pulls the &lt;code&gt;bouinecache/bouine&lt;/code&gt; image from Docker Hub by default.&lt;/p&gt;



&lt;div class="expressive-code"&gt;
 &lt;figure class="frame is-terminal not-content"&gt;
 &lt;figcaption class="header"&gt;
 &lt;span class="title"&gt;&lt;/span&gt;
 &lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm repo add bouine https://charts.bouine.org
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm repo update
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm search repo bouine&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/figure&gt;
&lt;/div&gt;



&lt;div class="expressive-code"&gt;
 &lt;figure class="frame not-content"&gt;
 &lt;figcaption class="header"&gt;
 &lt;span class="title"&gt;&lt;/span&gt;
 &lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NAME CHART VERSION APP VERSION DESCRIPTION
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bouine/bouine 0.1.0 0.1.0 Cloud-native HTTP cache in Go ...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/figure&gt;
&lt;/div&gt;
&lt;h2 id="helm-quickstart"&gt;Helm quickstart&lt;/h2&gt;



&lt;div class="expressive-code"&gt;
 &lt;figure class="frame is-terminal not-content"&gt;
 &lt;figcaption class="header"&gt;
 &lt;span class="title"&gt;&lt;/span&gt;
 &lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm install bouine bouine/bouine &lt;span style="color:#f1fa8c"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --namespace bouine --create-namespace &lt;span style="color:#f1fa8c"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --set &lt;span style="color:#f1fa8c"&gt;&amp;#34;config.upstream_pools[0].name=app&amp;#34;&lt;/span&gt; &lt;span style="color:#f1fa8c"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --set &lt;span style="color:#f1fa8c"&gt;&amp;#34;config.upstream_pools[0].targets[0]=app.default.svc:8080&amp;#34;&lt;/span&gt; &lt;span style="color:#f1fa8c"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --set &lt;span style="color:#f1fa8c"&gt;&amp;#34;config.routes[0].pool=app&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;This deploys a StatefulSet with gossip clustering, a headless Service for
peer discovery, and a PodDisruptionBudget.&lt;/p&gt;</description></item><item><title>Monitoring</title><link>https://bouine.org/v0.4/docs/operations/monitoring/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/operations/monitoring/</guid><description>&lt;h2 id="prometheus-metrics"&gt;Prometheus metrics&lt;/h2&gt;
&lt;p&gt;All metrics are exposed at &lt;code&gt;GET /metrics&lt;/code&gt; on the admin port (default &lt;code&gt;:9000&lt;/code&gt;) in Prometheus text format. No authentication is required to scrape this endpoint.&lt;/p&gt;
&lt;h3 id="traffic-red"&gt;Traffic (RED)&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Metric&lt;/th&gt;
 &lt;th&gt;Labels&lt;/th&gt;
 &lt;th&gt;Description&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;bouine_requests_total&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;method&lt;/code&gt;, &lt;code&gt;status&lt;/code&gt;, &lt;code&gt;cache_result&lt;/code&gt;, &lt;code&gt;source&lt;/code&gt;, &lt;code&gt;route&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Total requests processed. &lt;strong&gt;This is the primary RED counter.&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;bouine_request_duration_seconds&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;method&lt;/code&gt;, &lt;code&gt;status&lt;/code&gt;, &lt;code&gt;cache_result&lt;/code&gt;, &lt;code&gt;source&lt;/code&gt;, &lt;code&gt;route&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Request latency histogram. Includes native histogram buckets for higher-resolution percentiles. Carries Prometheus &lt;strong&gt;exemplars&lt;/strong&gt; linking high-latency observations to a trace ID when tracing is enabled.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;bouine_response_bytes_total&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;method&lt;/code&gt;, &lt;code&gt;cache_result&lt;/code&gt;, &lt;code&gt;source&lt;/code&gt;, &lt;code&gt;route&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Total bytes written in responses.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;cache_result&lt;/code&gt;&lt;/strong&gt; values: &lt;code&gt;HIT&lt;/code&gt;, &lt;code&gt;MISS&lt;/code&gt;, &lt;code&gt;STALE&lt;/code&gt;, &lt;code&gt;REVALIDATED&lt;/code&gt;, &lt;code&gt;BYPASS&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>TLS</title><link>https://bouine.org/v0.4/docs/configuration/tls/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/configuration/tls/</guid><description>&lt;p&gt;bouine terminates TLS natively for HTTP/1.1. No external TLS proxy is needed.&lt;/p&gt;
&lt;h2 id="minimal-tls-config"&gt;Minimal TLS config&lt;/h2&gt;



&lt;div class="expressive-code"&gt;
 &lt;figure class="frame not-content"&gt;
 &lt;figcaption class="header"&gt;
 &lt;span class="title"&gt;&lt;/span&gt;
 &lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff79c6"&gt;listen&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;https&lt;/span&gt;: &lt;span style="color:#f1fa8c"&gt;&amp;#34;:443&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;admin&lt;/span&gt;: &lt;span style="color:#f1fa8c"&gt;&amp;#34;:9000&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff79c6"&gt;tls&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;certs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ff79c6"&gt;cert_file&lt;/span&gt;: /etc/bouine/tls/cert.pem
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;key_file&lt;/span&gt;: /etc/bouine/tls/key.pem&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/figure&gt;
&lt;/div&gt;
&lt;h2 id="multiple-certificates-sni"&gt;Multiple certificates (SNI)&lt;/h2&gt;
&lt;p&gt;Serve different certificates per hostname:&lt;/p&gt;</description></item><item><title>Clustering</title><link>https://bouine.org/v0.4/docs/configuration/cluster-modes/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/configuration/cluster-modes/</guid><description>&lt;p&gt;Cluster mode lets multiple bouine pods share cache reads, broadcast invalidations, and reduce origin load.&lt;/p&gt;
&lt;h2 id="choosing-a-mode"&gt;Choosing a mode&lt;/h2&gt;



&lt;div class="expressive-code"&gt;
 &lt;figure class="frame not-content"&gt;
 &lt;figcaption class="header"&gt;
 &lt;span class="title"&gt;&lt;/span&gt;
 &lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff79c6"&gt;listen&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;cluster&lt;/span&gt;: &lt;span style="color:#f1fa8c"&gt;&amp;#34;:8443&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff79c6"&gt;cluster&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;mode&lt;/span&gt;: strong &lt;span style="color:#6272a4"&gt;# &amp;#34;strong&amp;#34; (default) | &amp;#34;eventual&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;Use this decision guide:&lt;/p&gt;</description></item><item><title>Dashboard</title><link>https://bouine.org/v0.4/docs/operations/dashboard/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/operations/dashboard/</guid><description>&lt;p&gt;The operator dashboard is embedded directly in the admin server — no extra process, no Node toolchain. Open it at:&lt;/p&gt;



&lt;div class="expressive-code"&gt;
 &lt;figure class="frame not-content"&gt;
 &lt;figcaption class="header"&gt;
 &lt;span class="title"&gt;&lt;/span&gt;
 &lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;http://&amp;lt;admin-addr&amp;gt;/dashboard/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;Default on localhost: &lt;strong&gt;

&lt;a class="link link--text" href="http://localhost:9000/dashboard/" rel="external"&gt;http://localhost:9000/dashboard/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="logging-in"&gt;Logging in&lt;/h2&gt;
&lt;p&gt;The dashboard uses a session cookie derived from the admin bearer token.&lt;/p&gt;</description></item><item><title>Example configurations</title><link>https://bouine.org/v0.4/docs/getting-started/examples/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/getting-started/examples/</guid><description>&lt;h2 id="static-site--blog"&gt;Static site / blog&lt;/h2&gt;



&lt;div class="expressive-code"&gt;
 &lt;figure class="frame not-content"&gt;
 &lt;figcaption class="header"&gt;
 &lt;span class="title"&gt;&lt;/span&gt;
 &lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff79c6"&gt;listen&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;http&lt;/span&gt;: &lt;span style="color:#f1fa8c"&gt;&amp;#34;:8080&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;admin&lt;/span&gt;: &lt;span style="color:#f1fa8c"&gt;&amp;#34;:9000&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff79c6"&gt;storage&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;hot_max_bytes&lt;/span&gt;: 64Mo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff79c6"&gt;upstream_pools&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ff79c6"&gt;name&lt;/span&gt;: site
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;targets&lt;/span&gt;: [&lt;span style="color:#f1fa8c"&gt;&amp;#34;site.default.svc.cluster.local:80&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff79c6"&gt;routes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ff79c6"&gt;match&lt;/span&gt;: { &lt;span style="color:#ff79c6"&gt;path_prefix&lt;/span&gt;: /assets/ }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;pool&lt;/span&gt;: site
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;cache&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;ttl_default&lt;/span&gt;: 86400s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;stale_if_error&lt;/span&gt;: 604800s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;jitter_percent&lt;/span&gt;: &lt;span style="color:#bd93f9"&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ff79c6"&gt;match&lt;/span&gt;: { &lt;span style="color:#ff79c6"&gt;path_prefix&lt;/span&gt;: / }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;pool&lt;/span&gt;: site
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;cache&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;ttl_default&lt;/span&gt;: 300s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;stale_while_revalidate&lt;/span&gt;: 60s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;stale_if_error&lt;/span&gt;: 86400s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff79c6"&gt;jitter_percent&lt;/span&gt;: &lt;span style="color:#bd93f9"&gt;15&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/figure&gt;
&lt;/div&gt;
&lt;h2 id="self-served-static-site-no-origin-server"&gt;Self-served static site (no origin server)&lt;/h2&gt;
&lt;p&gt;bouine can serve files directly from disk — no separate nginx or Caddy
needed. See 

&lt;a class="link link--text" href="https://bouine.org/v0.4/docs/configuration/static-files/"&gt;Static file serving&lt;/a&gt; for
the full reference.&lt;/p&gt;</description></item><item><title>Kubernetes operations</title><link>https://bouine.org/v0.4/docs/operations/kubernetes/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/operations/kubernetes/</guid><description>&lt;h2 id="scaling"&gt;Scaling&lt;/h2&gt;



&lt;div class="expressive-code"&gt;
 &lt;figure class="frame is-terminal not-content"&gt;
 &lt;figcaption class="header"&gt;
 &lt;span class="title"&gt;&lt;/span&gt;
 &lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl scale statefulset/bouine -n &amp;lt;namespace&amp;gt; --replicas&lt;span style="color:#ff79c6"&gt;=&lt;/span&gt;&lt;span style="color:#bd93f9"&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;Gossip auto-discovers peers via the headless Service DNS. New pods join the cluster within 60s.&lt;/p&gt;
&lt;h2 id="rolling-update-zero-5xx"&gt;Rolling update (zero 5xx)&lt;/h2&gt;



&lt;div class="expressive-code"&gt;
 &lt;figure class="frame is-terminal not-content"&gt;
 &lt;figcaption class="header"&gt;
 &lt;span class="title"&gt;&lt;/span&gt;
 &lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl rollout restart statefulset/bouine -n &amp;lt;namespace&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl rollout status statefulset/bouine -n &amp;lt;namespace&amp;gt; --timeout&lt;span style="color:#ff79c6"&gt;=&lt;/span&gt;180s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;StatefulSet rolls one pod at a time (reverse ordinal). Each pod must pass the readiness probe (&lt;code&gt;GET /readyz&lt;/code&gt;) before the next is replaced.&lt;/p&gt;</description></item><item><title>Observability guide</title><link>https://bouine.org/v0.4/docs/operations/observability/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/operations/observability/</guid><description>&lt;p&gt;This guide walks you through deploying a complete observability stack for bouine using the &lt;strong&gt;Grafana LGTM&lt;/strong&gt; components (Loki, Grafana, Tempo, Mimir/Prometheus) and &lt;strong&gt;Grafana Alloy&lt;/strong&gt; as the unified collection agent.&lt;/p&gt;
&lt;h2 id="architecture"&gt;Architecture&lt;/h2&gt;



&lt;div class="expressive-code"&gt;
 &lt;figure class="frame not-content"&gt;
 &lt;figcaption class="header"&gt;
 &lt;span class="title"&gt;&lt;/span&gt;
 &lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; monitoring namespace
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ┌──────────────────────────────────────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; │ Grafana ──queries──▶ Prometheus (metrics) │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; │ Loki (logs) │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; │ Tempo (traces) │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; │ ▲ ▲ ▲ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; │ Grafana Alloy (single agent) │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; └─────────────────────│────│────│──────────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; scrape :9000│ │OTLP :4318
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tail pod logs (k8s API) │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; bouine pods&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Grafana Alloy&lt;/strong&gt; replaces three separate agents:&lt;/p&gt;</description></item><item><title>Benchmarks</title><link>https://bouine.org/v0.4/docs/guides/benchmarks/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/guides/benchmarks/</guid><description>&lt;blockquote&gt;
&lt;h2 id="disclaimer"&gt;Disclaimer&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Benchmarks are synthetic.&lt;/strong&gt; They measure isolated behavior in artificial conditions.
Production workloads have different allocation patterns, concurrency levels, GC
pressure, network conditions, and hardware. The Varnish and NGINX configurations used
in these tests could likely be improved — a differently tuned Varnish or NGINX may
produce different results. Benchmarking is genuinely hard, and these numbers should be
treated as directional indicators, not as definitive performance claims.&lt;/p&gt;</description></item><item><title>Helm chart reference</title><link>https://bouine.org/v0.4/docs/configuration/helm/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/configuration/helm/</guid><description>&lt;p&gt;The Helm chart deploys bouine as a StatefulSet with headless Service for gossip peer discovery. Source: 

&lt;a class="link link--text" href="https://github.com/bouine-cache/bouine/tree/main/deploy/helm/bouine" rel="external"&gt;&lt;code&gt;deploy/helm/bouine/&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="install"&gt;Install&lt;/h2&gt;



&lt;div class="expressive-code"&gt;
 &lt;figure class="frame is-terminal not-content"&gt;
 &lt;figcaption class="header"&gt;
 &lt;span class="title"&gt;&lt;/span&gt;
 &lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm repo add bouine https://charts.bouine.org
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm repo update
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm install bouine bouine/bouine &lt;span style="color:#f1fa8c"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --namespace bouine --create-namespace &lt;span style="color:#f1fa8c"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --set &lt;span style="color:#f1fa8c"&gt;&amp;#34;config.upstream_pools[0].name=app&amp;#34;&lt;/span&gt; &lt;span style="color:#f1fa8c"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --set &lt;span style="color:#f1fa8c"&gt;&amp;#34;config.upstream_pools[0].targets[0]=app.default.svc:8080&amp;#34;&lt;/span&gt; &lt;span style="color:#f1fa8c"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --set &lt;span style="color:#f1fa8c"&gt;&amp;#34;config.routes[0].pool=app&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;To install from a local checkout, replace &lt;code&gt;bouine/bouine&lt;/code&gt; with the chart
directory &lt;code&gt;deploy/helm/bouine&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Experimental features</title><link>https://bouine.org/v0.4/docs/configuration/experimental/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/configuration/experimental/</guid><description>&lt;p&gt;Experimental features are opt-in capabilities that bypass some of bouine&amp;rsquo;s standard processing paths for improved performance. They are gated behind the &lt;code&gt;experimental&lt;/code&gt; config section and default to off.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; Experimental features may change or be removed between releases. Test thoroughly before enabling in production.&lt;/p&gt;</description></item><item><title>Production readiness checklist</title><link>https://bouine.org/v0.4/docs/guides/production-checklist/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/guides/production-checklist/</guid><description>&lt;p&gt;Before deploying bouine to production, verify each item below. Items
are grouped by area. Skip items that don&amp;rsquo;t apply to your deployment.&lt;/p&gt;
&lt;h2 id="tls-and-network-security"&gt;TLS and network security&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Data-plane TLS configured (if terminating HTTPS at bouine)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Cluster mTLS enabled (cert + key + CA bundle for peer-to-peer)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Admin port not exposed externally (NetworkPolicy or firewall)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Admin token set via Secret or environment variable (not auto-generated)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;insecure_skip_verify&lt;/code&gt; is not set in any upstream pool TLS config&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Hop-by-hop headers stripped (handled automatically by bouine)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="resource-sizing"&gt;Resource sizing&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;resources.limits.memory&lt;/code&gt; set and GOMEMLIMIT auto-computed (Helm chart does this)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;hot_max_bytes&lt;/code&gt; sized to fit in RAM without GC pressure (default: 75% of GOMEMLIMIT)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Warm tier PVC sized for working set (&lt;code&gt;warmVolume.size&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;warm_max_bytes&lt;/code&gt; set below PVC capacity to leave headroom&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;max_object_size&lt;/code&gt; configured per route to reject oversized responses&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;max_response_bytes&lt;/code&gt; configured to prevent memory exhaustion from large bodies&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="cluster-and-high-availability"&gt;Cluster and high availability&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;replicaCount &amp;gt;= 3&lt;/code&gt; for quorum&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;podDisruptionBudget.enabled: true&lt;/code&gt; with &lt;code&gt;minAvailable &amp;gt;= 2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Topology spread constraints set across zones&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;hop_limit&lt;/code&gt; configured (default 2 is fine for most deployments)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;terminationGracePeriodSeconds &amp;gt;= 40&lt;/code&gt; to allow graceful drain&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;minReadySeconds &amp;gt;= 30&lt;/code&gt; to let the ring converge before traffic&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="caching-policy"&gt;Caching policy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Every route has &lt;code&gt;ttl_default&lt;/code&gt; set explicitly&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;stale_while_revalidate&lt;/code&gt; configured for routes that can serve stale&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;stale_if_error&lt;/code&gt; configured for origin-outage resilience&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;negative_ttl&lt;/code&gt; set for routes that return errors (prevents error storms)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;jitter_percent &amp;gt; 0&lt;/code&gt; to prevent synchronized revalidation bursts&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;allow_set_cookie&lt;/code&gt; is off unless you explicitly need Set-Cookie caching&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Cache key configuration reviewed (query param stripping, header includes)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="upstream-and-origin"&gt;Upstream and origin&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Active health checks enabled per pool&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Passive health checks enabled (&lt;code&gt;consecutive_5xx&lt;/code&gt;, &lt;code&gt;eject_for&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Upstream connection timeout and response header timeout configured&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;max_connections&lt;/code&gt; set per pool to prevent FD exhaustion&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Hedged requests enabled for latency-sensitive routes&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="observability"&gt;Observability&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Prometheus scraping enabled (ServiceMonitor or PodMonitor)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Grafana dashboards imported (RED, storage, cluster, ops)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Alerting rules deployed (hit rate, error rate, peer fetch, warm tier)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; OpenTelemetry tracing endpoint configured (or disabled explicitly)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Access log sampling rate appropriate (default 1:100 for 200s)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;pprof_enabled&lt;/code&gt; is off in production (default)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="kubernetes-deployment"&gt;Kubernetes deployment&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Helm chart deployed with production values (&lt;code&gt;values-production.yaml&lt;/code&gt; as base)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;NetworkPolicy.enabled: true&lt;/code&gt; to isolate admin and cluster ports&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;serviceAccount.automount: false&lt;/code&gt; (bouine doesn&amp;rsquo;t need K8s API access)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Probes configured: startup (30 min budget), readiness (&lt;code&gt;/readyz&lt;/code&gt;), liveness (&lt;code&gt;/healthz&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Rolling update strategy: &lt;code&gt;maxUnavailable: 1&lt;/code&gt; for sequential pod restarts&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Config changes deployed via rolling update (no live config reload)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="operations"&gt;Operations&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Purge and ban workflows documented for on-call&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Runbook accessible (see 

&lt;a class="link link--text" href="https://bouine.org/v0.4/docs/operations/"&gt;operations docs&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Backup strategy for warm tier (PVC snapshots or rebuild from origin)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Drain procedure tested (&lt;code&gt;/drain&lt;/code&gt; endpoint + preStop hook)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Config file stored in version control&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Cloudflare CDN propagation</title><link>https://bouine.org/v0.4/docs/operations/cloudflare/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/operations/cloudflare/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;When bouine sits behind Cloudflare (or any scenario where Cloudflare caches
responses delivered through bouine), invalidating a URL in bouine is not
enough — the entry may also be cached at the Cloudflare edge.&lt;/p&gt;</description></item><item><title>Service mesh compatibility</title><link>https://bouine.org/v0.4/docs/guides/service-mesh/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/guides/service-mesh/</guid><description>&lt;p&gt;bouine works with any service mesh that operates at L4/L7. The main
consideration is the double-TLS problem: if the mesh enforces mTLS
between sidecars, bouine must either terminate TLS itself or let the
sidecar handle it.&lt;/p&gt;</description></item><item><title>Example Post</title><link>https://bouine.org/v0.4/blog/example/</link><pubDate>Mon, 16 Feb 2026 16:31:32 +0100</pubDate><guid>https://bouine.org/v0.4/blog/example/</guid><description>Use blog posts to communicate product updates and new features in a clear and consistent format.</description></item><item><title>CLI</title><link>https://bouine.org/v0.4/docs/reference/cli/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/reference/cli/</guid><description>&lt;h2 id="commands"&gt;Commands&lt;/h2&gt;



&lt;div class="expressive-code"&gt;
 &lt;figure class="frame is-terminal not-content"&gt;
 &lt;figcaption class="header"&gt;
 &lt;span class="title"&gt;&lt;/span&gt;
 &lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bouine serve --config /etc/bouine/config.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bouine config validate &amp;lt;file&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bouine config schema
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bouine completion bash|zsh|fish
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bouine purge &amp;lt;url&amp;gt; --token &amp;lt;token&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bouine ban &lt;span style="color:#8be9fd;font-style:italic"&gt;host_regex&lt;/span&gt;&lt;span style="color:#ff79c6"&gt;=&lt;/span&gt;example.com &lt;span style="color:#8be9fd;font-style:italic"&gt;path_regex&lt;/span&gt;&lt;span style="color:#ff79c6"&gt;=&lt;/span&gt;^/api --token &amp;lt;token&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bouine refresh &amp;lt;url&amp;gt; --token &amp;lt;token&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bouine cluster peers
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bouine version&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;--server&lt;/code&gt; defaults to &lt;code&gt;127.0.0.1:9000&lt;/code&gt;. All commands default to port 9000 so &lt;code&gt;--server&lt;/code&gt; is optional when running locally.&lt;/p&gt;</description></item><item><title>Admin API</title><link>https://bouine.org/v0.4/docs/reference/api/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/reference/api/</guid><description>&lt;h2 id="authentication"&gt;Authentication&lt;/h2&gt;
&lt;p&gt;All write endpoints require a bearer token. See 

&lt;a class="link link--text" href="https://bouine.org/v0.4/docs/operations/authentication/"&gt;Authentication&lt;/a&gt; for full details on token resolution, environment variables, and config file setup.&lt;/p&gt;
&lt;p&gt;Pass the token in requests:&lt;/p&gt;



&lt;div class="expressive-code"&gt;
 &lt;figure class="frame is-terminal not-content"&gt;
 &lt;figcaption class="header"&gt;
 &lt;span class="title"&gt;&lt;/span&gt;
 &lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -X POST http://127.0.0.1:9000/v1/purge &lt;span style="color:#f1fa8c"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -H &lt;span style="color:#f1fa8c"&gt;&amp;#34;Authorization: Bearer your-secret-token&amp;#34;&lt;/span&gt; &lt;span style="color:#f1fa8c"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -H &lt;span style="color:#f1fa8c"&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; &lt;span style="color:#f1fa8c"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -d &lt;span style="color:#f1fa8c"&gt;&amp;#39;{&amp;#34;url&amp;#34;:&amp;#34;https://example.com/page&amp;#34;}&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/figure&gt;
&lt;/div&gt;
&lt;h2 id="exempt-endpoints-no-token-required"&gt;Exempt endpoints (no token required)&lt;/h2&gt;
&lt;p&gt;These are always accessible without authentication — required for K8s probes and Prometheus scraping:&lt;/p&gt;</description></item><item><title>Response headers</title><link>https://bouine.org/v0.4/docs/reference/headers/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/reference/headers/</guid><description>&lt;h2 id="x-cache"&gt;X-Cache&lt;/h2&gt;
&lt;p&gt;Indicates how the response was served.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Value&lt;/th&gt;
 &lt;th&gt;Description&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;HIT&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Served from cache (fresh)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;MISS&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Fetched from origin and cached&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;STALE&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Served from cache (stale, within stale-while-revalidate or stale-if-error window)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;BYPASS&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Cache bypassed (no-store, no-cache, or cache disabled for route)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;REVALIDATED&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Conditional request to origin returned 304, served from cache with updated freshness&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;



&lt;div class="expressive-code"&gt;
 &lt;figure class="frame is-terminal not-content"&gt;
 &lt;figcaption class="header"&gt;
 &lt;span class="title"&gt;&lt;/span&gt;
 &lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -sI http://localhost:8080/get | grep x-cache
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6272a4"&gt;# X-Cache: HIT&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/figure&gt;
&lt;/div&gt;
&lt;h2 id="age"&gt;Age&lt;/h2&gt;
&lt;p&gt;The age of the cached object in seconds, calculated as the time since the
&lt;code&gt;Date&lt;/code&gt; header of the original response plus any time spent in upstream
forward proxies. Updated on every cache hit.&lt;/p&gt;</description></item><item><title>Go SDK</title><link>https://bouine.org/v0.4/docs/reference/go-sdk/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/reference/go-sdk/</guid><description>&lt;p&gt;The bouine Go SDK (&lt;code&gt;pkg/bouineapi&lt;/code&gt;) provides typed methods for every
admin API endpoint. It shares wire types with the Cobra CLI and the
admin server, so there is no drift between the SDK and the API.&lt;/p&gt;</description></item><item><title>FAQ</title><link>https://bouine.org/v0.4/docs/faq/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/faq/</guid><description>&lt;h2 id="general"&gt;General&lt;/h2&gt;
&lt;h3 id="how-is-bouine-different-from-varnish"&gt;How is bouine different from Varnish?&lt;/h3&gt;
&lt;p&gt;bouine is designed for Kubernetes from day one: gossip clustering, Helm
chart, Prometheus metrics, and OpenTelemetry tracing are built-in. Varnish
requires commercial Varnish Plus or external orchestration for clustering,
and uses VCL (an imperative DSL) instead of declarative YAML. See the


&lt;a class="link link--text" href="../guides/varnish-migration/"&gt;migration guide&lt;/a&gt; for a side-by-side comparison.&lt;/p&gt;</description></item><item><title>Troubleshooting</title><link>https://bouine.org/v0.4/docs/operations/troubleshooting/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/docs/operations/troubleshooting/</guid><description>&lt;h2 id="quick-reference"&gt;Quick reference&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Symptom&lt;/th&gt;
 &lt;th&gt;Severity&lt;/th&gt;
 &lt;th&gt;Jump to&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Pods don&amp;rsquo;t discover each other&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;Critical&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;

&lt;a class="link link--text" href="https://bouine.org/v0.4/docs/operations/troubleshooting/#pods-do-not-discover-each-other"&gt;Cluster discovery&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Rolling restart produces 503/502&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;High&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;

&lt;a class="link link--text" href="https://bouine.org/v0.4/docs/operations/troubleshooting/#rolling-restart-produces-503502"&gt;Rolling restart&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Purge doesn&amp;rsquo;t propagate&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;High&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;

&lt;a class="link link--text" href="https://bouine.org/v0.4/docs/operations/troubleshooting/#purge-does-not-propagate-across-cluster"&gt;Purge propagation&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;HIT p99 spikes to 50–100 ms under load&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;High&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;

&lt;a class="link link--text" href="https://bouine.org/v0.4/docs/operations/troubleshooting/#hit-p99-spikes-to-50100-ms-under-load"&gt;GC stop-the-world pauses&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;X-Cache&lt;/code&gt; always MISS&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;Medium&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;

&lt;a class="link link--text" href="https://bouine.org/v0.4/docs/operations/troubleshooting/#x-cache-is-always-miss"&gt;Cache misses&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Stale reads on one node&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;Medium&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;

&lt;a class="link link--text" href="https://bouine.org/v0.4/docs/operations/troubleshooting/#stale-reads"&gt;Stale reads&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Low hit rate in eventual mode&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;Low&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;

&lt;a class="link link--text" href="https://bouine.org/v0.4/docs/operations/troubleshooting/#low-hit-rate-in-eventual-mode"&gt;Low hit rate&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Docker build slow on Apple Silicon&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;Low&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;

&lt;a class="link link--text" href="https://bouine.org/v0.4/docs/operations/troubleshooting/#docker-build-is-slow-on-apple-silicon"&gt;Docker build&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="cluster-discovery"&gt;Cluster discovery&lt;/h2&gt;
&lt;h3 id="pods-do-not-discover-each-other"&gt;Pods do not discover each other&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Check the headless Service:&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Example Guide</title><link>https://bouine.org/v0.4/docs/guides/example/</link><pubDate>Thu, 07 Sep 2023 16:04:48 +0200</pubDate><guid>https://bouine.org/v0.4/docs/guides/example/</guid><description>&lt;p&gt;Guides lead a user through a specific task they want to accomplish, often with a sequence of steps. Writing a good guide requires thinking about what your users are trying to do.&lt;/p&gt;</description></item><item><title>Example Reference</title><link>https://bouine.org/v0.4/docs/reference/example/</link><pubDate>Thu, 07 Sep 2023 16:13:18 +0200</pubDate><guid>https://bouine.org/v0.4/docs/reference/example/</guid><description>&lt;p&gt;Reference pages are ideal for outlining how things work in terse and clear terms. Less concerned with telling a story or addressing a specific use case, they should give a comprehensive outline of what your documenting.&lt;/p&gt;</description></item><item><title>Resources</title><link>https://bouine.org/v0.4/docs/resources/</link><pubDate>Tue, 27 Feb 2024 09:30:56 +0100</pubDate><guid>https://bouine.org/v0.4/docs/resources/</guid><description>&lt;p&gt;Link to valuable, relevant resources.&lt;/p&gt;</description></item><item><title>404</title><link>https://bouine.org/v0.4/404/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/404/</guid><description/></item><item><title>Privacy Policy</title><link>https://bouine.org/v0.4/privacy/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bouine.org/v0.4/privacy/</guid><description/></item></channel></rss>