<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Best Practices on Strata Documentation</title><link>https://danchupin.github.io/strata/best-practices/</link><description>Recent content in Best Practices on Strata Documentation</description><generator>Hugo</generator><language>en</language><atom:link href="https://danchupin.github.io/strata/best-practices/index.xml" rel="self" type="application/rss+xml"/><item><title>Web UI (Strata Console)</title><link>https://danchupin.github.io/strata/best-practices/web-ui/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://danchupin.github.io/strata/best-practices/web-ui/</guid><description>&lt;h1 id="strata-console-web-ui--operator-guide"&gt;Strata Console (Web UI) — Operator Guide&lt;a class="anchor" href="#strata-console-web-ui--operator-guide"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The Strata Console is an embedded read-only web UI for cluster operators.
It ships in the same binary as the gateway (&lt;code&gt;go:embed&lt;/code&gt;) and is served at
&lt;code&gt;/console/&lt;/code&gt; on the gateway HTTP port. No separate process, no separate
deploy.&lt;/p&gt;
&lt;p&gt;This document is the Phase 1 (foundation) operator guide. Phase 2 (admin
write actions) and Phase 3 (debug tooling — heatmaps, slow queries, OTel
trace browser) ship in their own cycles.&lt;/p&gt;</description></item><item><title>Tracing</title><link>https://danchupin.github.io/strata/best-practices/tracing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://danchupin.github.io/strata/best-practices/tracing/</guid><description>&lt;h1 id="tracing"&gt;Tracing&lt;a class="anchor" href="#tracing"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Strata emits OpenTelemetry spans across every meaningful tier of the
request and worker paths. Each span carries the &lt;code&gt;strata.component&lt;/code&gt;
attribute so an operator can filter the entire gateway path or the
entire worker path in one Jaeger query, and each worker iteration
appears as a discrete trace so a slow / failing tick is easy to
correlate with the meta + data ops it triggered.&lt;/p&gt;
&lt;p&gt;The wire-up env vars + tail-sampler + ring buffer behaviour live in
&lt;a href="https://danchupin.github.io/strata/operate/monitoring/#opentelemetry-tracing"&gt;Monitoring&lt;/a&gt;.
This page is the operator-facing reference for &lt;strong&gt;what spans exist,
how they are named, and how to filter them&lt;/strong&gt;.&lt;/p&gt;</description></item><item><title>GC + lifecycle tuning</title><link>https://danchupin.github.io/strata/best-practices/gc-lifecycle-tuning/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://danchupin.github.io/strata/best-practices/gc-lifecycle-tuning/</guid><description>&lt;h1 id="gc--lifecycle-tuning"&gt;GC + lifecycle tuning&lt;a class="anchor" href="#gc--lifecycle-tuning"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The gc and lifecycle workers run inside every gateway replica. The
operator-facing knobs split into two layers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Phase 1 — per-replica fan-out:&lt;/strong&gt; &lt;code&gt;STRATA_GC_CONCURRENCY&lt;/code&gt; /
&lt;code&gt;STRATA_LIFECYCLE_CONCURRENCY&lt;/code&gt; cap the goroutine count inside one
replica&amp;rsquo;s worker.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Phase 2 — multi-replica sharding:&lt;/strong&gt; &lt;code&gt;STRATA_GC_SHARDS&lt;/code&gt; shards the
leader-election space so N replicas process disjoint slices of the
queue in parallel.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both layers compose: a 3-replica deploy with &lt;code&gt;STRATA_GC_SHARDS=3&lt;/code&gt; and
per-replica &lt;code&gt;STRATA_GC_CONCURRENCY=64&lt;/code&gt; runs three independent fan-outs
against disjoint shards.&lt;/p&gt;</description></item><item><title>Quotas + billing</title><link>https://danchupin.github.io/strata/best-practices/quotas-billing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://danchupin.github.io/strata/best-practices/quotas-billing/</guid><description>&lt;h1 id="quotas--billing"&gt;Quotas + billing&lt;a class="anchor" href="#quotas--billing"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Strata enforces hard per-bucket and per-user storage quotas at PUT-validate
time and emits a nightly per-(bucket, storage class) usage aggregate that an
external invoice generator can consume. The shape mirrors AWS / RGW so a
RADOS Gateway tenant migrating to Strata sees the same &lt;code&gt;QuotaExceeded&lt;/code&gt; 403
on overage.&lt;/p&gt;
&lt;p&gt;The cycle stops at the usage feed. Invoice ledger / payment integration
lives in a separate ops-layer service that consumes &lt;code&gt;usage_aggregates&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Production hardening</title><link>https://danchupin.github.io/strata/best-practices/production-hardening/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://danchupin.github.io/strata/best-practices/production-hardening/</guid><description>&lt;h1 id="production-hardening"&gt;Production hardening&lt;a class="anchor" href="#production-hardening"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;12-line checklist to run through before flipping a Strata replica into
prod traffic. Each line links to the runbook section that explains the
knob, the metric, and the failure mode it prevents. Every knob is opt-in
and zero-by-default — running through the list flips a memory / lab
deployment into a prod-ready shape without touching code.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;#&lt;/th&gt;
 &lt;th&gt;Check&lt;/th&gt;
 &lt;th&gt;Runbook&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;1&lt;/td&gt;
 &lt;td&gt;HTTP server timeouts non-zero (&lt;code&gt;STRATA_HTTP_READ_HEADER_TIMEOUT=10s&lt;/code&gt; / &lt;code&gt;STRATA_HTTP_READ_TIMEOUT=60s&lt;/code&gt; / &lt;code&gt;STRATA_HTTP_WRITE_TIMEOUT=30m&lt;/code&gt; / &lt;code&gt;STRATA_HTTP_IDLE_TIMEOUT=120s&lt;/code&gt; / &lt;code&gt;STRATA_HTTP_MAX_HEADER_BYTES=1048576&lt;/code&gt;). Defaults already match — only verify if you tuned them.&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://danchupin.github.io/strata/reference/env-vars/#gateway-core-http"&gt;STRATA_HTTP_*&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;2&lt;/td&gt;
 &lt;td&gt;TLS terminated on the gateway (&lt;code&gt;STRATA_TLS_CERT_FILE&lt;/code&gt; / &lt;code&gt;STRATA_TLS_KEY_FILE&lt;/code&gt;, or &lt;code&gt;STRATA_TLS_CERT_DIR&lt;/code&gt; for SNI multi-tenant) — or behind an ingress with &lt;code&gt;STRATA_TRUSTED_PROXIES&lt;/code&gt; set to the ingress source CIDR.&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://danchupin.github.io/strata/operate/tls-termination/#deploy-shapes"&gt;TLS termination — shapes B/C&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;3&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;STRATA_TLS_MIN_VERSION=TLS1.2&lt;/code&gt; (default) and &lt;code&gt;STRATA_TLS_CIPHER_PROFILE=mozilla-modern&lt;/code&gt; (default). Bump &lt;code&gt;MIN_VERSION=TLS1.3&lt;/code&gt; if every client supports it.&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://danchupin.github.io/strata/operate/tls-termination/#deploy-shapes"&gt;TLS shapes&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;4&lt;/td&gt;
 &lt;td&gt;Cert hot-reload enabled (&lt;code&gt;STRATA_TLS_RELOAD_INTERVAL=60s&lt;/code&gt;, default) so cert-manager / Vault PKI rotation is picked up without restart.&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://danchupin.github.io/strata/operate/tls-termination/#cert-manager-kubernetes"&gt;cert-manager recipe&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;5&lt;/td&gt;
 &lt;td&gt;Admin / console / metrics on a separate listener (&lt;code&gt;STRATA_ADMIN_LISTEN=127.0.0.1:9001&lt;/code&gt; recommended; loopback or RFC1918 only). Optionally pin operator client certs via &lt;code&gt;STRATA_ADMIN_TLS_CLIENT_CA_FILE&lt;/code&gt;.&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://danchupin.github.io/strata/operate/tls-termination/#shape-c--strata-terminated-split-admin--s3-listeners"&gt;Shape C — split admin listener&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;6&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;STRATA_TRUSTED_PROXIES&lt;/code&gt; set to the ingress / LB source CIDR. Default empty = &lt;code&gt;X-Forwarded-*&lt;/code&gt; ignored. Required for the &lt;code&gt;Secure&lt;/code&gt; cookie flag + audit-log client-IP fidelity behind any proxy.&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://github.com/danchupin/strata/blob/main/README.md#breaking-changes"&gt;Trusted proxies — README breaking change&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;7&lt;/td&gt;
 &lt;td&gt;Per-IP + per-key ingress rate limit on (&lt;code&gt;STRATA_RATE_LIMIT_PER_IP=N&lt;/code&gt; and / or &lt;code&gt;STRATA_RATE_LIMIT_PER_KEY=N&lt;/code&gt;). Default 0 = disabled. Refusal returns HTTP 429 + &lt;code&gt;&amp;lt;Code&amp;gt;SlowDown&amp;lt;/Code&amp;gt;&lt;/code&gt;.&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://danchupin.github.io/strata/reference/env-vars/#gateway-core-http"&gt;STRATA_RATE_LIMIT_*&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;8&lt;/td&gt;
 &lt;td&gt;Cassandra mTLS (&lt;code&gt;STRATA_CASSANDRA_TLS_CA_FILE&lt;/code&gt; + &lt;code&gt;STRATA_CASSANDRA_TLS_CERT_FILE&lt;/code&gt; + &lt;code&gt;STRATA_CASSANDRA_TLS_KEY_FILE&lt;/code&gt;). &lt;code&gt;SKIP_VERIFY&lt;/code&gt; must be &lt;code&gt;false&lt;/code&gt; (default).&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://danchupin.github.io/strata/operate/tls-termination/#cassandra"&gt;Cassandra mTLS&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;9&lt;/td&gt;
 &lt;td&gt;TiKV mTLS (&lt;code&gt;STRATA_TIKV_TLS_CA_FILE&lt;/code&gt; is &lt;strong&gt;required&lt;/strong&gt; when any other TLS knob is set — the upstream silently downgrades on empty CA). PD endpoints accept &lt;code&gt;https://&lt;/code&gt;.&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://danchupin.github.io/strata/operate/tls-termination/#tikv"&gt;TiKV mTLS&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;10&lt;/td&gt;
 &lt;td&gt;S3-upstream mTLS (&lt;code&gt;STRATA_S3_TLS_*&lt;/code&gt; global default; per-cluster &lt;code&gt;tls&lt;/code&gt; override on &lt;code&gt;STRATA_S3_CLUSTERS&lt;/code&gt; JSON wins outright per cluster).&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://danchupin.github.io/strata/operate/tls-termination/#s3-upstream"&gt;S3-upstream mTLS&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;11&lt;/td&gt;
 &lt;td&gt;RADOS cephx in place — &lt;code&gt;STRATA_RADOS_KEYRING&lt;/code&gt; populated; &lt;code&gt;ms_cluster_mode=secure&lt;/code&gt; set in &lt;code&gt;ceph.conf&lt;/code&gt; if wire-level confidentiality is required. (No Strata-side TLS knob for RADOS.)&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://danchupin.github.io/strata/operate/tls-termination/#rados-uses-cephx-not-tls"&gt;RADOS uses cephx&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;12&lt;/td&gt;
 &lt;td&gt;Prometheus alert on &lt;code&gt;sum(strata_backend_tls_skip_verify) &amp;gt; 0&lt;/code&gt; (any backend with &lt;code&gt;SKIP_VERIFY=true&lt;/code&gt;) AND on &lt;code&gt;rate(strata_ingress_rate_limit_refused_total[5m]) &amp;gt; N&lt;/code&gt; (sustained client floods).&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://danchupin.github.io/strata/operate/monitoring/"&gt;Monitoring — alert recipes&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="what-this-checklist-closes"&gt;What this checklist closes&lt;a class="anchor" href="#what-this-checklist-closes"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Every line above closes a P0 gap from the 2026-05-25 prod-readiness
audit:&lt;/p&gt;</description></item><item><title>S3 multi-cluster routing</title><link>https://danchupin.github.io/strata/best-practices/s3-multi-cluster/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://danchupin.github.io/strata/best-practices/s3-multi-cluster/</guid><description>&lt;h1 id="s3-multi-cluster-routing"&gt;S3 multi-cluster routing&lt;a class="anchor" href="#s3-multi-cluster-routing"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The S3 data backend supports routing per storage class to a distinct
&lt;code&gt;(cluster, bucket)&lt;/code&gt; pair. Two envs hold the full config — &lt;code&gt;STRATA_S3_CLUSTERS&lt;/code&gt;
(JSON array of bucket-less cluster specs) and &lt;code&gt;STRATA_S3_CLASSES&lt;/code&gt; (JSON object
mapping storage class names to &lt;code&gt;{cluster, bucket}&lt;/code&gt; tuples). Adding or removing
a cluster requires a gateway restart; multi-replica deployments hide
per-instance downtime via rolling restart.&lt;/p&gt;
&lt;p&gt;This page is the operator guide. For the conceptual S3 backend overview see
&lt;a href="https://danchupin.github.io/strata/architecture/backends/s3/"&gt;S3 data backend&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Compliance</title><link>https://danchupin.github.io/strata/best-practices/compliance/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://danchupin.github.io/strata/best-practices/compliance/</guid><description>&lt;h1 id="compliance"&gt;Compliance&lt;a class="anchor" href="#compliance"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Strata implements S3 Object Lock with COMPLIANCE and GOVERNANCE retention
modes plus legal hold. COMPLIANCE rows are immutable until their
&lt;code&gt;RetainUntilDate&lt;/code&gt; elapses — not even the bucket owner can shorten the
retention window or delete the object early. The audit log records every
COMPLIANCE-mode write and every expiry the lifecycle worker performs so
auditors can grep &lt;code&gt;audit_log&lt;/code&gt; for retention-policy events with a single
&lt;code&gt;action LIKE 'objectlock:%'&lt;/code&gt; clause.&lt;/p&gt;
&lt;p&gt;This page is the operator workflow guide. For the audit-log shape see
&lt;a href="https://danchupin.github.io/strata/operate/monitoring/#audit-log"&gt;Monitoring — audit log&lt;/a&gt;; for
the underlying retention semantics see the &lt;a href="https://danchupin.github.io/strata/s3-compatibility/"&gt;S3 Compatibility&lt;/a&gt;
matrix.&lt;/p&gt;</description></item><item><title>Placement + rebalance</title><link>https://danchupin.github.io/strata/best-practices/placement-rebalance/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://danchupin.github.io/strata/best-practices/placement-rebalance/</guid><description>&lt;h1 id="placement--rebalance"&gt;Placement + rebalance&lt;a class="anchor" href="#placement--rebalance"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Once you run more than one RADOS / S3 cluster behind a single Strata
deployment, you also need to control &lt;strong&gt;which&lt;/strong&gt; cluster a bucket&amp;rsquo;s chunks
land on and how to migrate old chunks when a new cluster joins or an
old cluster is being retired. Strata ships both pieces:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A per-bucket &lt;strong&gt;placement policy&lt;/strong&gt; (&lt;code&gt;meta.Bucket.Placement&lt;/code&gt; — a
&lt;code&gt;{cluster: weight}&lt;/code&gt; map) that the chunk PUT path consults via a
stable hash-mod router.&lt;/li&gt;
&lt;li&gt;A leader-elected &lt;strong&gt;rebalance worker&lt;/strong&gt; (&lt;code&gt;strata server --workers=rebalance&lt;/code&gt;)
that walks every bucket with a non-nil policy, compares the actual
per-cluster chunk distribution to the policy&amp;rsquo;s target, and copies
chunks A → B until the two match.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A bucket without a policy (&lt;code&gt;Placement == nil&lt;/code&gt;) behaves exactly as
before — chunks land on the storage class&amp;rsquo;s default cluster. No
migration, no schema bump, no behavior change. The policy + worker are
both opt-in.&lt;/p&gt;</description></item><item><title>Billing</title><link>https://danchupin.github.io/strata/best-practices/billing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://danchupin.github.io/strata/best-practices/billing/</guid><description>&lt;h1 id="billing"&gt;Billing&lt;a class="anchor" href="#billing"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Strata does not ship an invoice generator. It ships the &lt;strong&gt;inputs an
external invoice generator can consume&lt;/strong&gt;: a daily per-(bucket, storage
class) row in &lt;code&gt;usage_aggregates&lt;/code&gt; whose &lt;code&gt;byte_seconds&lt;/code&gt; field integrates
the bucket-usage counter across the UTC day with the trapezoid rule.&lt;/p&gt;
&lt;p&gt;This page documents the integration math, the sampling cadence, and the
env knob that tunes accuracy vs. meta-backend cost. For the live quota
counter, the &lt;code&gt;QuotaExceeded&lt;/code&gt; shape, the reconcile worker, and the admin
API surface, see &lt;a href="https://danchupin.github.io/strata/best-practices/quotas-billing/"&gt;Quotas + billing&lt;/a&gt;.&lt;/p&gt;</description></item></channel></rss>