Configuration Reference
All configurable environment variables across Sukko services. Values are set via env: struct tags in Go config files — the envDefault is the source of truth for defaults.
Shared (Base)
| Variable | Type | Default | Description |
|---|---|---|---|
LOG_LEVEL | string | info | Logging level (debug, info, warn, error). info is recommended for production. |
LOG_FORMAT | string | json | Log output format: json for machine parsing (production), text for human-readable (development). |
ENVIRONMENT | string | local | Deployment environment name (e.g. local, dev, stag, prod). Used for Kafka topic namespace resolution. |
SUKKO_LICENSE_KEY | string | — | Sukko license token (JWT). Community edition has no key; Pro/Enterprise obtain via Sukko account. Leave empty for Community. |
OTEL_TRACING_ENABLED | bool | false | Enable distributed tracing via OpenTelemetry. Disabled by default; configure OTEL_EXPORTER_TYPE and OTEL_EXPORTER_ENDPOINT when enabled. |
OTEL_EXPORTER_TYPE | string | otlp-grpc | OpenTelemetry trace exporter type: otlp-grpc, otlp-http, or stdout. Required when OTEL_TRACING_ENABLED=true. |
OTEL_EXPORTER_ENDPOINT | string | localhost:4317 | OpenTelemetry collector endpoint (e.g. otelcol:4317). Required when OTEL_EXPORTER_TYPE is otlp-grpc or otlp-http. |
PPROF_ENABLED | bool | false | Enable Go pprof profiling endpoints (/debug/pprof/). Disabled by default; enable only in controlled environments. |
PYROSCOPE_ENABLED | bool | false | Enable continuous profiling via Pyroscope. Disabled by default. |
PYROSCOPE_ADDR | string | http://localhost:4040 | Pyroscope server address (e.g. http://pyroscope:4040). Required when PYROSCOPE_ENABLED=true. |
AUTH_MODE | string | required | Authentication enforcement mode. Only "required" is supported; tokens without valid signatures are rejected. |
PROVISIONING_GRPC_ADDR | string | localhost:9090 | gRPC address of the provisioning service for internal communication (e.g. channel rule streaming). |
HTTP_READ_TIMEOUT | time.Duration | 15s | Maximum duration for reading a complete HTTP request. Protects against slow-loris attacks. |
HTTP_WRITE_TIMEOUT | time.Duration | 15s | Maximum duration for writing the HTTP response. |
HTTP_IDLE_TIMEOUT | time.Duration | 60s | Maximum idle time on a keep-alive connection before it is closed. |
KAFKA_TOPIC_NAMESPACE | string | — | Explicit Kafka topic namespace prefix ({namespace}.{tenant}.{suffix}); required when the service builds or parses namespaced topics; validated against VALID_NAMESPACES. |
VALID_NAMESPACES | string | local,dev,stag,prod | Comma-separated list of allowed Kafka topic namespaces. Used to validate KAFKA_TOPIC_NAMESPACE. |
KAFKA_BROKERS | string | — | Comma-separated Kafka/Redpanda broker addresses for ws-server, push, and the tester's kafka-ingest suite (provisioning uses PROVISIONING_KAFKA_BROKERS instead). Required when MESSAGE_BACKEND=kafka; no default. |
KAFKA_SASL_ENABLED | bool | false | Enable SASL authentication for Kafka connections. Required for most managed Kafka/Redpanda services. |
KAFKA_SASL_MECHANISM | string | — | SASL mechanism: plain, scram-sha-256, or scram-sha-512. Required when KAFKA_SASL_ENABLED=true. |
KAFKA_SASL_USERNAME | string | — | SASL username for Kafka authentication. Required when KAFKA_SASL_ENABLED=true. |
KAFKA_SASL_PASSWORD | string | — | SASL password for Kafka authentication. Required when KAFKA_SASL_ENABLED=true. |
KAFKA_TLS_ENABLED | bool | false | Enable TLS encryption for Kafka connections. Required for most managed Kafka/Redpanda services. |
KAFKA_TLS_INSECURE | bool | false | Skip TLS certificate verification. For development only — never use in production. |
KAFKA_TLS_CA_PATH | string | — | Path to CA certificate file for verifying the Kafka broker's TLS certificate. |
MESSAGE_BACKEND | string | direct | Message ingestion backend: direct (no persistence, no Kafka dependency) or kafka (full Kafka/Redpanda integration with replay). |
DATABASE_URL | string | — | PostgreSQL connection URL (postgres://user:pass@host:5432/db). Required for services that use the database (provisioning, push). |
Gateway
| Variable | Type | Default | Description |
|---|---|---|---|
GATEWAY_PORT | int | 3000 | HTTP listen port for the WebSocket gateway. |
GATEWAY_READ_TIMEOUT | time.Duration | 15s | HTTP server read timeout. Applies to the WebSocket upgrade handshake and HTTP request reads. |
GATEWAY_WRITE_TIMEOUT | time.Duration | 15s | HTTP server write timeout. |
GATEWAY_IDLE_TIMEOUT | time.Duration | 60s | HTTP keep-alive idle timeout. Connections idle longer than this are closed. |
GATEWAY_BACKEND_URL | string | ws://localhost:3005/ws | WebSocket URL of the ws-server backend the gateway proxies connections to. Must include the /ws path. |
GATEWAY_DIAL_TIMEOUT | time.Duration | 10s | Timeout for dialing the ws-server backend when establishing a new proxied connection. |
GATEWAY_MESSAGE_TIMEOUT | time.Duration | 60s | Timeout for forwarding a single message between a client and the ws-server backend. |
GATEWAY_MAX_FRAME_SIZE | int | 1048576 | Maximum WebSocket frame size in bytes. Frames larger than this are rejected before allocation. Default: 1MB. |
REQUIRE_TENANT_ID | bool | true | When true, all WebSocket connections must identify a tenant via their JWT or API key. Disable only in single-tenant deployments where the tenant is implicit. |
DEFAULT_TENANT_CONNECTION_LIMIT | int | 1000 | Default maximum simultaneous WebSocket connections allowed per tenant when TENANT_CONNECTION_LIMIT_ENABLED is true. |
TENANT_CONNECTION_LIMIT_ENABLED | bool | false | When true, the gateway enforces per-tenant connection limits using DEFAULT_TENANT_CONNECTION_LIMIT as the default cap. |
GATEWAY_PUBLISH_RATE_LIMIT | float64 | 10.0 | Sustained rate limit for REST and WebSocket publish requests per authenticated principal, in messages per second. |
GATEWAY_PUBLISH_BURST | int | 100 | Burst allowance for the REST and WebSocket publish rate limiter. Allows short spikes above GATEWAY_PUBLISH_RATE_LIMIT before throttling kicks in. |
GATEWAY_MAX_PUBLISH_SIZE | int | 65536 | Maximum REST publish payload size in bytes. Payloads exceeding this are rejected. Default: 64KB. |
GATEWAY_AUTH_REFRESH_RATE_INTERVAL | time.Duration | 30s | Minimum interval between JWT refresh operations per connection. Prevents refresh storms under load. |
GATEWAY_AUTH_VALIDATION_TIMEOUT | time.Duration | 5s | Timeout for validating auth refresh operations per connection. |
REVOCATION_MAX_LIFETIME | time.Duration | 24h | Max time a revocation entry lives when exp is not provided |
GATEWAY_SHUTDOWN_TIMEOUT | time.Duration | 30s | Maximum time the gateway waits for active connections to drain before forcing shutdown. |
WS_INTERNAL_SECRET | string | — | Shared secret forwarded as X-Sukko-Internal-Secret to ws-server. Set WS_INTERNAL_SECRET_ENABLED=true on ws-server to enforce. |
SERVER_GRPC_ADDR | string | localhost:3006 | ws-server gRPC address for RealtimeService |
GATEWAY_PUSH_ENABLED | bool | false | Enables the gateway's push endpoints and push-service client; when false the /api/v1/push/* routes are not registered (404) and no push connection is made. Explicit deployment mode — the push service is deploy-optional. |
PUSH_GRPC_ADDR | string | localhost:3008 | Push service gRPC address for device registration and VAPID key endpoints; required (and used) only when GATEWAY_PUSH_ENABLED=true. |
SSE_KEEPALIVE_INTERVAL | time.Duration | 45s | Interval for SSE keepalive messages sent to prevent proxy timeouts on long-lived connections. |
SSE_CURSOR_EVERY_N | int | 20 | Emit the Last-Event-ID reconnect cursor at most every Nth delivered SSE message (and on each keepalive tick if it advanced), keeping the per-message delivery path light; a client resuming from a slightly-stale cursor replays a few extra messages, deduplicated by mid. |
SSE_MAX_CHANNELS | int | 64 | Maximum channels a single SSE connection may subscribe to; bounds the reconnect cursor token so it stays within request-header size limits. |
GATEWAY_CORS_ORIGINS | []string | * | CORS allowed origins (* = all, production: restrict) |
GATEWAY_CHANNEL_RULES_CACHE_TTL | time.Duration | 1m | How long per-tenant channel rules are cached locally before re-fetching from the provisioning service. |
GATEWAY_REGISTRY_QUERY_TIMEOUT | time.Duration | 5s | Timeout for querying the connections registry when enforcing per-tenant connection limits. |
Core
| Variable | Type | Default | Description |
|---|---|---|---|
WS_ADDR | string | :3002 | HTTP listen address for the WebSocket load balancer. |
WS_NUM_SHARDS | int | 1 | Number of independent connection-routing shards. Higher values reduce lock contention; increase WS_BASE_PORT range accordingly. |
WS_BASE_PORT | int | 3002 | Base port for shard binding (3002, 3003, ...) |
WS_LB_ADDR | string | :3005 | Load balancer listen address |
SERVER_GRPC_PORT | int | 3006 | gRPC server port for RealtimeService (SSE Subscribe + REST Publish) |
KAFKA_CONSUMER_ENABLED | bool | true | When false, the Kafka consumer pool is disabled and no messages are consumed from Kafka topics. Useful for debug deployments or when using an alternative message backend. |
KAFKA_DEFAULT_PARTITIONS | int | 1 | Default partition count for Kafka topics created on demand by ws-server. |
KAFKA_DEFAULT_REPLICATION_FACTOR | int | 1 | Default replication factor for Kafka topics created on demand by ws-server. |
WS_MEMORY_LIMIT | int64 | 536870912 | Memory limit in bytes. New connections are rejected (HTTP 503) when exceeded. Default: 512MB. |
WS_MAX_CONNECTIONS | int | 500 | Maximum simultaneous WebSocket client connections per pod. New connections are rejected with HTTP 503 when this limit is reached. |
WS_MAX_KAFKA_RATE | int | 1000 | Maximum Kafka messages per second the server consumes across all topics; exceeding it paces (backpressures) consumption rather than dropping, so sustained overload becomes consumer lag, not message loss. |
WS_MAX_BROADCAST_RATE | int | 25 | Maximum Valkey broadcast fan-out rate in messages per second. Messages above this rate are dropped and counted in ws_broadcast_bus_dropped_total. |
WS_MAX_GOROUTINES | int | 100000 | Maximum number of goroutines allowed per pod. New connections are rejected when this limit is reached. |
WS_RATE_LIMIT_BURST_MULTIPLIER | int | 2 | Burst capacity as a multiple of the steady-state rate |
WS_CLIENT_MSG_BURST_LIMIT | int | 100 | Per-client inbound message burst capacity (token bucket). Clients exceeding this are disconnected. |
WS_CLIENT_MSG_RATE_PER_SEC | float64 | 10 | Per-client sustained rate/sec |
CONN_RATE_LIMIT_ENABLED | bool | true | When true, connection rate limiting is enforced per source IP and globally to protect against connection flood attacks. Controlled by CONN_RATE_LIMIT_IP_RATE, CONN_RATE_LIMIT_IP_BURST, CONN_RATE_LIMIT_GLOBAL_RATE, and CONN_RATE_LIMIT_GLOBAL_BURST. |
CONN_RATE_LIMIT_IP_BURST | int | 100 | Burst allowance for per-source-IP connection rate limiting. |
CONN_RATE_LIMIT_IP_RATE | float64 | 100.0 | Sustained new-connection rate limit per source IP address, in connections per second. |
CONN_RATE_LIMIT_GLOBAL_BURST | int | 300 | Burst allowance for the global (all-IP combined) new-connection rate limit. |
CONN_RATE_LIMIT_GLOBAL_RATE | float64 | 50.0 | Sustained new-connection rate limit across all source IPs combined, in connections per second. |
WS_CPU_REJECT_THRESHOLD | float64 | 60.0 | CPU percentage above which new connections are rejected with HTTP 503. Hysteresis: stop rejecting below WS_CPU_REJECT_THRESHOLD_LOWER. |
WS_CPU_REJECT_THRESHOLD_LOWER | float64 | 0 | CPU percentage below which connection rejection stops (hysteresis lower bound). 0 = auto: WS_CPU_REJECT_THRESHOLD minus 10. |
WS_CPU_PAUSE_THRESHOLD | float64 | 70.0 | CPU percentage above which Kafka consumption is paused. Hysteresis: resume below WS_CPU_PAUSE_THRESHOLD_LOWER. |
WS_CPU_PAUSE_THRESHOLD_LOWER | float64 | 0 | CPU percentage below which the Kafka consumer pauses end (hysteresis lower bound). 0 = auto: WS_CPU_PAUSE_THRESHOLD minus 10. |
WS_CPU_EWMA_BETA | float64 | 0.8 | EWMA decay factor for CPU smoothing (0-1, higher = smoother) |
TCP_LISTEN_BACKLOG | int | 2048 | TCP accept queue size (0 = Go default ~128) |
METRICS_INTERVAL | time.Duration | 15s | Prometheus metrics collection interval for system-level metrics (CPU usage, memory, connection counts). |
CPU_POLL_INTERVAL | time.Duration | 1s | Interval for CPU usage sampling used by backpressure and connection rejection decisions. Lower values detect spikes faster at marginally higher overhead. |
ALERT_ENABLED | bool | false | When true, ws-server sends operational alerts to the configured destinations (ALERT_SLACK_WEBHOOK_URL, ALERT_CONSOLE_ENABLED). |
ALERT_MIN_LEVEL | string | WARNING | Minimum alert severity to send. One of: DEBUG, INFO, WARNING, ERROR, CRITICAL. |
ALERT_SLACK_WEBHOOK_URL | string | — | Slack incoming webhook URL for alert delivery. |
ALERT_SLACK_CHANNEL | string | — | Slack channel to post alerts to (e.g. #ops-alerts). |
ALERT_SLACK_USERNAME | string | AlertBot | Display name for the Slack alert bot. |
ALERT_SLACK_TIMEOUT | time.Duration | 5s | HTTP request timeout for each Slack webhook delivery attempt. |
ALERT_RATE_LIMIT_WINDOW | time.Duration | 5m | Window duration for alert rate limiting. At most ALERT_RATE_LIMIT_MAX alerts are sent per window. |
ALERT_RATE_LIMIT_MAX | int | 3 | Maximum alerts sent per ALERT_RATE_LIMIT_WINDOW. Excess alerts are suppressed to prevent notification floods. |
ALERT_CONSOLE_ENABLED | bool | false | When true, alerts are written to the structured log output in addition to any remote destinations. |
VALKEY_ADDRS | []string | localhost:6379 | Valkey server addresses, comma-separated. For Sentinel high-availability, provide all Sentinel addresses (e.g. sentinel1:26379,sentinel2:26379,sentinel3:26379). For single-instance, provide one address. |
VALKEY_MASTER_NAME | string | mymaster | Valkey Sentinel master name. Only used when VALKEY_ADDRS contains Sentinel addresses. |
VALKEY_PASSWORD | string | — | Valkey authentication password. |
VALKEY_DB | int | 0 | Valkey database index. Use 0 (the default) unless your deployment requires database isolation. |
VALKEY_CHANNEL | string | ws.broadcast | Valkey pub/sub channel prefix. The full per-tenant channel is {VALKEY_CHANNEL}:{tenantID} (e.g. ws.broadcast:acme-corp). All ws-server pods must use the same prefix. If Valkey ACLs restrict pub/sub by channel pattern, update patterns from ws.broadcast to ws.broadcast:*. |
WS_SLOW_CLIENT_MAX_ATTEMPTS | int | 3 | Number of consecutive failed send attempts before a slow client is disconnected. A send attempt fails when the client's outbound buffer is full. |
WS_CLIENT_SEND_BUFFER_SIZE | int | 512 | Per-client outbound message buffer size in messages. Larger buffers tolerate temporary client slowness at the cost of higher memory usage per connection. |
WS_GAP_NOTIFY_BUFFER_SIZE | int | 8 | Per-client buffer for gap notification messages. Gap notifications are low-priority; this buffer absorbs bursts without blocking the main message pipeline. |
WS_REPLAY_RATE_LIMIT_INTERVAL | time.Duration | 10s | Minimum interval between history replay requests per client per channel. Prevents replay storms from a single connection. |
BROADCAST_TYPE | string | valkey | Backend for inter-instance message broadcasting. Only valkey is supported — Valkey pub/sub is required for all ws-server deployments. |
VALKEY_TLS_ENABLED | bool | false | When true, Valkey connections use TLS encryption. Required for managed Valkey/Redis services (ElastiCache, Memorystore, Upstash). |
VALKEY_TLS_INSECURE | bool | false | When true, TLS certificate verification is skipped for Valkey connections. Do not use in production. |
VALKEY_TLS_CA_PATH | string | — | Path to a custom CA certificate file for Valkey TLS connections. Required when Valkey uses a private certificate authority. |
TOPIC_REFRESH_INTERVAL | time.Duration | 60s | How often ws-server re-syncs the tenant topic list from the provisioning registry. This is a safety net; the primary update path is event-driven. |
WS_PONG_WAIT | time.Duration | 60s | Timeout for receiving a pong response after sending a ping. Clients that do not respond within this window are disconnected. Must be greater than WS_PING_PERIOD. |
WS_PING_PERIOD | time.Duration | 45s | Interval between WebSocket ping frames sent to connected clients. Must be less than WS_PONG_WAIT. |
WS_WRITE_WAIT | time.Duration | 5s | Timeout for a single WebSocket write operation. Increase for high-latency networks. |
WS_REPLAY_TIMEOUT | time.Duration | 5s | Timeout for a single history replay handler to complete. |
WS_PUBLISH_TIMEOUT | time.Duration | 5s | Timeout for a client publish operation (client to gateway to ws-server to Kafka). |
WS_MAX_REPLAY_MESSAGES | int | 100 | Maximum number of messages returned per history replay request. |
WS_TOPIC_CREATION_TIMEOUT | time.Duration | 30s | Timeout for on-demand Kafka topic creation. |
WS_SHARD_DIAL_TIMEOUT | time.Duration | 10s | Timeout for the load balancer to dial a shard when proxying a new connection. |
WS_SHARD_MESSAGE_TIMEOUT | time.Duration | 60s | Timeout for forwarding a single message between the load balancer and a shard. |
WS_METRICS_AGGREGATION_INTERVAL | time.Duration | 5s | Interval for aggregating per-shard metrics into cluster-level summaries. |
WS_SHUTDOWN_GRACE_PERIOD | time.Duration | 30s | Maximum time ws-server waits for in-flight connections and consumers to drain during graceful shutdown. |
WS_SHUTDOWN_CHECK_INTERVAL | time.Duration | 1s | Polling interval for checking whether all connections have closed during graceful shutdown. |
WS_METRICS_COLLECT_INTERVAL | time.Duration | 2s | Interval for collecting internal runtime metrics (goroutine counts, buffer saturation). |
WS_MEMORY_MONITOR_INTERVAL | time.Duration | 30s | Interval for polling memory usage against WS_MEMORY_LIMIT. |
WS_MEMORY_WARNING_PERCENT | int | 80 | Memory usage percentage of WS_MEMORY_LIMIT at which a warning log is emitted. |
WS_MEMORY_CRITICAL_PERCENT | int | 90 | Memory usage percentage of WS_MEMORY_LIMIT at which new connections are rejected. |
WS_BUFFER_SAMPLE_INTERVAL | time.Duration | 10s | Interval for sampling client send buffer saturation metrics. |
WS_BUFFER_MAX_SAMPLES | int | 100 | Rolling window size in samples for buffer saturation statistics. |
WS_BUFFER_HIGH_SATURATION_PERCENT | int | 90 | Per-client send buffer fill percentage above which the client is considered saturated. |
WS_BUFFER_POPULATION_WARN_PERCENT | int | 25 | Percentage of clients considered saturated above which a warning alert is triggered. |
CONN_RATE_LIMIT_IP_TTL | time.Duration | 5m | How long per-IP connection rate limit state is retained after the last connection attempt from that IP. |
CONN_RATE_LIMIT_CLEANUP_INTERVAL | time.Duration | 1m | Interval for purging expired per-IP rate limit state. |
BROADCAST_BUFFER_SIZE | int | 256 | Per-tenant per-shard broadcast message buffer size. When this buffer is full, messages for that tenant are dropped and counted in ws_broadcast_bus_dropped_total. Maximum: 65,536 (BROADCAST_BUFFER_SIZE_MAX); values above this cause a startup failure. Operators running high-throughput single-tenant workloads should increase this value. |
BROADCAST_SHUTDOWN_TIMEOUT | time.Duration | 5s | Timeout for draining the broadcast bus during graceful shutdown. |
VALKEY_WRITE_TIMEOUT | time.Duration | 3s | Timeout for Valkey write operations (SET, EXPIRE) from the broadcast bus. |
VALKEY_PUBLISH_TIMEOUT | time.Duration | 100ms | Timeout for each Valkey PUBLISH command in the broadcast hot path. |
VALKEY_STARTUP_PING_TIMEOUT | time.Duration | 5s | Timeout for the Valkey connectivity check during ws-server startup. |
VALKEY_RECONNECT_INITIAL_BACKOFF | time.Duration | 100ms | Starting backoff delay for Valkey reconnection attempts after a connection failure. |
VALKEY_RECONNECT_MAX_BACKOFF | time.Duration | 30s | Maximum backoff delay between Valkey reconnection attempts. |
VALKEY_RECONNECT_MAX_ATTEMPTS | int | 10 | Maximum number of Valkey reconnection attempts before the broadcast bus is marked unhealthy. |
VALKEY_HEALTH_CHECK_INTERVAL | time.Duration | 10s | Interval for periodic Valkey health checks. |
VALKEY_HEALTH_CHECK_TIMEOUT | time.Duration | 5s | Timeout for each Valkey health check PING. |
VALKEY_PUBLISH_STALENESS_THRESHOLD | time.Duration | 60s | Staleness window for the Valkey broadcast publisher — a warning is logged if no message is published within this interval (indicates silent consumer failures). |
VALKEY_ZERO_SUBSCRIBER_WINDOW | time.Duration | 30s | How long a broadcast that reaches zero subscribers is held for retry after a Valkey pub/sub disruption before being flushed — bounds consume-loop backpressure so a genuinely empty channel cannot block ingestion indefinitely. |
KAFKA_BATCH_SIZE | int | 50 | Maximum number of Kafka messages processed per consumer batch. |
KAFKA_BATCH_TIMEOUT | time.Duration | 10ms | Maximum time to wait to fill a batch before processing it. |
KAFKA_METADATA_MIN_AGE | time.Duration | 5s | Minimum interval before the Kafka producer refreshes topic metadata (lower = faster new-topic produce, more metadata traffic). |
KAFKA_FETCH_MAX_WAIT | time.Duration | 500ms | Maximum time the Kafka broker waits before returning a fetch response, even if KAFKA_FETCH_MIN_BYTES has not been met. Lower values reduce latency; higher values improve throughput. |
KAFKA_FETCH_MIN_BYTES | int32 | 1 | Minimum bytes a broker should accumulate before returning a fetch response. |
KAFKA_FETCH_MAX_BYTES | int32 | 10485760 | Maximum bytes returned per fetch request. |
KAFKA_SESSION_TIMEOUT | time.Duration | 30s | Kafka consumer group session timeout. If the consumer does not heartbeat within this window, it is declared dead and a rebalance is triggered. Must be within the broker's configured range. |
KAFKA_REBALANCE_TIMEOUT | time.Duration | 60s | Maximum time allowed for a consumer group rebalance to complete. Must be greater than KAFKA_COMMIT_ON_REVOKE_TIMEOUT. |
KAFKA_REPLAY_FETCH_MAX_BYTES | int32 | 5242880 | Maximum bytes per fetch during history replay. Kept separate from KAFKA_FETCH_MAX_BYTES to prevent replay reads from saturating the live consumer path. |
KAFKA_BACKPRESSURE_CHECK_INTERVAL | time.Duration | 100ms | Polling interval for the Kafka backpressure circuit breaker (CPU and goroutine pressure check). |
KAFKA_COMMIT_ON_REVOKE_TIMEOUT | time.Duration | 5s | How long ws-server waits to commit processed Kafka offsets during a consumer group rebalance (triggered on rolling deploys, pod restarts, or scale events). If the commit completes within this window, duplicate delivery to clients by the new consumer is minimized. If the commit times out, offsets since the last background auto-commit (see KAFKA_AUTO_COMMIT_INTERVAL) may be re-delivered. |
KAFKA_AUTO_COMMIT_INTERVAL | time.Duration | 5s | Interval between background Kafka offset commits. Controls the crash-path duplicate window: if a pod crashes without a clean shutdown, messages processed in the final KAFKA_AUTO_COMMIT_INTERVAL before the crash may be re-delivered after failover. Lower values reduce the crash-path window at the cost of more frequent broker commits. Minimum: 100ms — values below this cause a startup validation error. |
KAFKA_PRODUCER_BATCH_MAX_BYTES | int | 1048576 | Maximum bytes per Kafka producer batch. |
KAFKA_PRODUCER_MAX_BUFFERED_RECORDS | int | 10000 | Maximum number of records buffered in the Kafka producer before backpressure is applied to callers. |
KAFKA_PRODUCER_RECORD_RETRIES | int | 8 | Number of retries for failed Kafka produce operations before the record is discarded. |
KAFKA_PRODUCER_CB_TIMEOUT | time.Duration | 30s | Circuit breaker observation window for Kafka producer failures. |
KAFKA_PRODUCER_CB_MAX_FAILURES | int | 5 | Maximum producer failures within the circuit breaker window before the producer circuit opens (pauses). |
KAFKA_PRODUCER_CB_HALF_OPEN_REQS | int | 1 | Number of test requests permitted when the Kafka producer circuit breaker is in half-open state. |
KAFKA_PRODUCER_SHUTDOWN_TIMEOUT | time.Duration | 10s | Maximum time to wait for in-flight Kafka fan-out/DLQ writes to finish during shutdown before force-closing the producer connection. |
WS_ROUTING_FANOUT_WORKERS | int | 4 | Number of parallel workers that produce a record to each Kafka topic when a routing rule fans a channel out to multiple topics. |
WS_ROUTING_FANOUT_QUEUE_SIZE | int | 256 | Queue depth for the Kafka multi-topic fan-out worker pool; when full, the overflowing topic write is routed to the dead-letter path. |
WS_ROUTING_DLQ_MAX_RETRIES | int | 3 | Maximum retry attempts for a failed dead-letter topic write before the record is discarded. |
WS_ROUTING_DLQ_BASE_DELAY | time.Duration | 100ms | Initial backoff delay before retrying a failed dead-letter topic write (exponential backoff starting point). |
WS_ROUTING_DLQ_MAX_DELAY | time.Duration | 5s | Maximum backoff delay cap for dead-letter topic write retries. |
WS_ROUTING_DLQ_RETRY_WORKERS | int | 4 | Number of parallel workers retrying failed dead-letter topic writes. |
WS_MAX_CHANNELS_PER_CLIENT | int | 100 | Maximum concurrent channel subscriptions per client connection. Subscription requests beyond this limit are rejected. |
WS_HISTORY_ENABLED | bool | false | When true, message history is retained in a Valkey Streams ring buffer with Kafka as a fallback for deeper replay. Enables client history replay requests. |
WS_HISTORY_BUFFER_DEPTH | int | 1000 | Maximum number of messages retained per channel in the Valkey Streams ring buffer (XADD MAXLEN ~). Older messages are evicted when the limit is reached. |
WS_HISTORY_TTL | time.Duration | 24h | Per-stream Valkey key expiry. Streams inactive longer than this duration are deleted to free memory. |
WS_HISTORY_WRITER_BUFFER | int | 10000 | Internal message queue depth for the history writer. Messages are dropped when this buffer is full. |
WS_HISTORY_MAX_LIMIT | int | 100 | Maximum number of messages a client may request in a single history replay call. |
WS_HISTORY_DELIVERY_TIMEOUT | time.Duration | 30s | Deadline for completing a single history replay request, including Valkey XREVRANGE and optional Kafka fallback reads. |
WS_HISTORY_WRITER_PIPELINE_BATCH | int | 50 | Maximum number of Valkey XADD commands per pipeline batch for history writes. |
WS_HISTORY_WRITER_LOCK_TTL | time.Duration | 10s | TTL for the distributed history writer lock in Valkey. The active writer pod renews this lock on each heartbeat interval. |
WS_HISTORY_WRITER_RESTART_INITIAL_BACKOFF | time.Duration | 500ms | Initial delay before restarting the history writer after a failure. |
WS_HISTORY_WRITER_RESTART_MAX_BACKOFF | time.Duration | 30s | Maximum delay between history writer restart attempts. |
WS_HISTORY_VALKEY_CMD_TIMEOUT | time.Duration | 2s | Per-command timeout for history Valkey operations (XADD, XREVRANGE, EXPIRE). |
WS_HISTORY_MAX_CONSECUTIVE_LOCK_FAILURES | int | 3 | Number of consecutive heartbeat lock renewal failures before the history writer steps down and triggers a restart. |
WS_HISTORY_WRITER_HEARTBEAT_INTERVAL | time.Duration | 3s | Interval for history writer lock renewal and broadcast bus health checks. |
WS_CONNECTIONS_REGISTRY_ENABLED | bool | false | When true, ws-server tracks active connections in Valkey and exposes them via the Connections Management API (Pro edition). Requires Valkey memory headroom proportional to active connections x subscriptions x average channel name length. |
WS_CONNECTIONS_REGISTRY_TTL | time.Duration | 120s | Valkey EXPIRE duration for each connection entry in the registry. Heartbeats renew the TTL; connections that fail to heartbeat within this window are treated as expired. |
WS_CONNECTIONS_REGISTRY_BUFFER | int | 1024 | Internal channel buffer for registry events (connect, disconnect, subscribe). Events are dropped when this buffer is full. |
WS_CONNECTIONS_REGISTRY_FLUSH_INTERVAL | time.Duration | 5s | Interval for flushing buffered registry events to Valkey. |
WS_CONNECTIONS_REGISTRY_HEARTBEAT_INTERVAL | time.Duration | 30s | Interval for renewing active connection TTLs in the registry. |
WS_CONNECTIONS_REGISTRY_RESTART_INITIAL_BACKOFF | time.Duration | 100ms | Initial delay before restarting the registry writer after a failure. |
WS_CONNECTIONS_REGISTRY_RESTART_MAX_BACKOFF | time.Duration | 30s | Maximum delay between registry writer restart attempts. |
WS_CONNECTIONS_REGISTRY_SHUTDOWN_DRAIN_TIMEOUT | time.Duration | 100ms | Time allowed to flush buffered registry events during graceful shutdown. Set to 0 to skip draining. |
WS_ADMIN_CHANNEL_SUBSCRIBE_TIMEOUT | time.Duration | 10s | Timeout for each shard's SUBSCRIBE call to the admin broadcast channel at startup. |
WS_INTERNAL_SECRET_ENABLED | bool | false | When true, ws-server validates the X-Sukko-Internal-Secret header on all incoming connections, rejecting any that bypass the gateway. |
WS_INTERNAL_SECRET | string | — | Shared secret validated as X-Sukko-Internal-Secret on incoming connections. Must match the value configured on the gateway. Required when WS_INTERNAL_SECRET_ENABLED is true. |
Provisioning
| Variable | Type | Default | Description |
|---|---|---|---|
ANALYTICS_PARTMAN_INTERVAL | time.Duration | 15m | Interval for running pg_partman maintenance on analytics partition tables. |
ANALYTICS_SSE_MAX_CONNS | int | 10 | Maximum concurrent SSE connections for the analytics streaming endpoint. |
PROVISIONING_KAFKA_BROKERS | string | localhost:19092 | Kafka broker addresses for provisioning-originated admin operations (topic creation, etc.). Comma-separated. |
PROVISIONING_ADDR | string | :8080 | HTTP listen address for the provisioning API. |
GRPC_PORT | int | 9090 | gRPC server port for internal service-to-service communication. |
ADMIN_BOOTSTRAP_KEY | string | — | Bootstrap admin API key for provisioning service. Required; used for initial tenant setup. |
DEFAULT_PARTITIONS | int | 3 | Default Kafka partition count assigned to new tenant topics. |
DEFAULT_RETENTION_MS | int64 | 604800000 | Default Kafka topic retention in milliseconds. Default: 604,800,000ms (7 days). |
MAX_TOPICS_PER_TENANT | int | 50 | Default maximum number of Kafka topics per tenant. |
MAX_PARTITIONS_PER_TENANT | int | 200 | Default maximum total partitions across all topics per tenant. |
MAX_STORAGE_BYTES | int64 | 10737418240 | Default maximum Kafka storage quota per tenant in bytes. Default: 10,737,418,240 (10GB). |
PRODUCER_BYTE_RATE | int64 | 10485760 | Default Kafka producer byte-rate quota per tenant in bytes/sec. Default: 10485760 (10MB/s). |
CONSUMER_BYTE_RATE | int64 | 52428800 | Default Kafka consumer byte-rate quota per tenant in bytes/sec. Default: 52428800 (50MB/s). |
DEPROVISION_GRACE_DAYS | int | 30 | Days to retain a deprovisioned tenant's Kafka topics and ACLs before permanent deletion. |
LIFECYCLE_CHECK_INTERVAL | time.Duration | 1h | How often the lifecycle manager scans for tenants due for deprovisioning or cleanup. |
LIFECYCLE_MANAGER_ENABLED | bool | true | Enables the background tenant lifecycle manager (deprovisioning, retention enforcement). |
MAX_ROUTING_RULES_PER_TENANT | int | 100 | Max routing rules per tenant |
MAX_TOPICS_PER_RULE | int | 10 | Max topic destinations per routing rule: 1 ingress topic plus up to MAX_TOPICS_PER_RULE-1 egress topics |
ROUTING_DLQ_TOPIC_PARTITIONS | int | 1 | Partitions for dead-letter topics |
ROUTING_DLQ_TOPIC_RETENTION_MS | int64 | 604800000 | Retention for dead-letter topics (7 days) |
INFRA_TOPIC_REPLICATION_FACTOR | int | 1 | Replication factor for all infrastructure topics (DLQ + default); use int — caarlos0/env v11 does not handle int16; cast to int16 at CreateTopic call sites |
API_RATE_LIMIT_PER_MIN | int | 60 | Maximum provisioning API requests per minute per IP before HTTP 429 is returned. |
KEY_REGISTRY_REFRESH_INTERVAL | time.Duration | 1m | How often the key registry polls for updated tenant JWT signing keys. |
KEY_REGISTRY_QUERY_TIMEOUT | time.Duration | 5s | Timeout for each key registry lookup query. |
SHUTDOWN_TIMEOUT | time.Duration | 30s | Maximum time to wait for in-flight requests during graceful shutdown. |
CORS_ALLOWED_ORIGINS | []string | http://localhost:3000 | Allowed origins for CORS preflight responses. Comma-separated; no wildcard in production. |
CORS_MAX_AGE | int | 3600 | Maximum seconds a CORS preflight response may be cached by the browser. |
PROVISIONING_MAX_TENANTS_FETCH_LIMIT | int | 10000 | Maximum number of tenants returned by internal bulk-fetch operations. |
PROVISIONING_DELETION_TIMEOUT | time.Duration | 5m | Timeout for a single tenant deletion operation (Kafka topic removal, ACL cleanup). |
SLUG_RENAME_TOPIC_HOLD_PERIOD | time.Duration | 168h | How long a tenant's previous slug is honored after a rename: retention window for old Kafka topics/ACLs, and the grace window during which old-slug JWTs are still accepted on both the provisioning API and the WebSocket gateway. Minimum 24h. |
PROVISIONING_TOKEN_REVOCATION_MAX_LIFETIME | time.Duration | 1h | Maximum duration to retain a revoked token record before the prune loop removes it. |
PROVISIONING_TOKEN_REVOCATION_RATE_LIMIT_PER_MIN | int | 30 | Maximum token-revocation requests per minute per IP before HTTP 429; independent of API_RATE_LIMIT_PER_MIN. |
PROVISIONING_TOKEN_REVOCATION_RATE_LIMIT_BURST | int | 5 | Burst allowance for token-revocation requests per IP before HTTP 429 is returned. |
PROVISIONING_VALKEY_ADDRS | []string | — | Valkey server addresses (host:port), comma-separated. For Sentinel mode, list all sentinels. |
PROVISIONING_VALKEY_PASSWORD | string | — | Valkey authentication password. Leave empty for unauthenticated local deployments. |
PROVISIONING_VALKEY_MASTER_NAME | string | — | Sentinel master name. Required when using Valkey Sentinel for high availability. |
PROVISIONING_VALKEY_TLS_ENABLED | bool | false | Enable TLS for Valkey connections. Required for managed Valkey services. |
PROVISIONING_VALKEY_TLS_INSECURE | bool | false | Skip Valkey TLS certificate verification. For development only. |
PROVISIONING_VALKEY_TLS_CA_PATH | string | — | Path to CA certificate file for verifying the Valkey server's TLS certificate. |
PROVISIONING_BULK_DISCONNECT_CONCURRENCY | int | 10 | Maximum concurrent Valkey publishes during a bulk connection disconnect request. |
MAX_WEBHOOKS_PER_TENANT | int | 10 | Maximum number of webhook endpoint registrations per tenant. |
WEBHOOK_DOWNGRADE_POLL_INTERVAL | time.Duration | 5m | Polling interval for checking whether a tenant's webhook delivery should pause due to edition downgrade. |
WEBHOOK_WORKER_GRPC_PORT | int | 9091 | gRPC listen port for the webhook-worker internal service. Must differ from GRPC_PORT. |
WEBHOOK_WORKER_GRPC_ADDR | string | — | gRPC address provisioning dials to reach the webhook-worker service. Required for Pro/Enterprise editions. |
Shared Webhook Configuration
note
These variables must be set identically across both the provisioning service and the webhook-worker. Setting them differently causes authentication failures or silent credential decryption mismatches.
| Variable | Type | Default | Description |
|---|---|---|---|
WEBHOOK_ALLOW_HTTP | bool | false | Allow webhook delivery to plain HTTP endpoints. Disabled by default; enable only in trusted network environments. |
WEBHOOK_INTERNAL_TOKEN | string | — | Shared secret for authenticating internal webhook reload calls between the provisioning service and webhook worker. |
CREDENTIALS_ENCRYPTION_KEY | string | — | AES encryption key (hex-encoded, 32 bytes) for encrypting sensitive credentials at rest (push provider keys and webhook signing secrets). |
Webhook Worker
| Variable | Type | Default | Description |
|---|---|---|---|
WEBHOOK_ALLOW_PRIVATE_IPS | bool | false | Allow webhook delivery to private-IP endpoints (disables SSRF protection). Safe default: false; enable only in trusted environments via explicit opt-in. |
WEBHOOK_HTTP_PORT | int | 8083 | HTTP port for the webhook worker's management API. |
WEBHOOK_WORKER_INTERNAL_GRPC_PORT | int | 9095 | gRPC port for internal communication between provisioning service and webhook worker. |
WEBHOOK_WORKER_PROVISIONING_GRPC_ADDR | string | — | gRPC address of the provisioning service for webhook configuration queries. |
WEBHOOK_WORKER_CONCURRENCY | int | 50 | Maximum number of concurrent webhook delivery goroutines. |
WEBHOOK_WORKER_RETRY_QUEUE_SIZE | int | 10000 | In-memory retry queue capacity. Webhooks failing initial delivery are queued here. |
WEBHOOK_DELIVERY_TIMEOUT | time.Duration | 10s | HTTP timeout for a single webhook delivery attempt. |
WEBHOOK_CACHE_TTL | time.Duration | 30s | TTL for cached webhook endpoint configurations fetched from provisioning. |
WEBHOOK_WORKER_VALKEY_ADDRS | []string | — | Valkey server addresses (host:port), comma-separated. For Sentinel mode, list all sentinels. |
WEBHOOK_WORKER_VALKEY_PASSWORD | string | — | Valkey authentication password. Leave empty for unauthenticated local deployments. |
WEBHOOK_WORKER_VALKEY_MASTER_NAME | string | — | Sentinel master name. Required when using Valkey Sentinel for high availability. |
WEBHOOK_WORKER_VALKEY_TLS_ENABLED | bool | false | Enable TLS for Valkey connections. Required for managed Valkey services. |
WEBHOOK_WORKER_VALKEY_TLS_INSECURE | bool | false | Skip Valkey TLS certificate verification. For development only. |
WEBHOOK_WORKER_VALKEY_TLS_CA_PATH | string | — | Path to CA certificate file for verifying the Valkey server's TLS certificate. |
WEBHOOK_WORKER_VALKEY_CHANNEL | string | ws.broadcast | Valkey pub/sub channel prefix for broadcast events. MUST match ws-server's VALKEY_CHANNEL or the worker receives no events (the full per-tenant channel is {prefix}:{tenantID}). |
WEBHOOK_WORKER_VALKEY_STARTUP_PING_TIMEOUT | time.Duration | 5s | Timeout for the Valkey connectivity check during webhook-worker startup. Must be > 0 or the check fails instantly. |
WEBHOOK_WORKER_VALKEY_WRITE_TIMEOUT | time.Duration | 3s | Timeout for Valkey write operations (SUBSCRIBE/PSUBSCRIBE) from the broadcast bus. |
WEBHOOK_WORKER_VALKEY_HEALTH_CHECK_INTERVAL | time.Duration | 10s | Interval for periodic Valkey health checks. Must be > 0 or the health monitor is disabled. |
WEBHOOK_WORKER_VALKEY_HEALTH_CHECK_TIMEOUT | time.Duration | 5s | Timeout for each Valkey health check PING. |
WEBHOOK_WORKER_BROADCAST_SHUTDOWN_TIMEOUT | time.Duration | 5s | Timeout for draining the broadcast bus during graceful shutdown. |
PROVISIONING_GRPC_RECONNECT_DELAY | time.Duration | 1s | Initial backoff delay between provisioning gRPC stream reconnect attempts. Configures the webhook-worker's outbound gRPC client connection to the provisioning service — the provisioning process does not read these vars. |
PROVISIONING_GRPC_RECONNECT_MAX_DELAY | time.Duration | 30s | Maximum backoff delay cap for provisioning gRPC stream reconnect attempts. Configures the webhook-worker's outbound gRPC client connection to the provisioning service — the provisioning process does not read these vars. |
Tester
| Variable | Type | Default | Description |
|---|---|---|---|
TESTER_PORT | int | 8090 | HTTP port the tester service listens on for test run management and SSE metric streaming. |
TESTER_AUTH_TOKEN | string | — | Bearer token required for all tester management API endpoints. Must be set explicitly — the tester rejects requests when unset. |
GATEWAY_URL | string | ws://localhost:3000 | WebSocket URL of the gateway that test connections will target. |
PROVISIONING_URL | string | http://localhost:8080 | HTTP base URL of the provisioning service used to create test tenants and API keys. |
TESTER_SIGNING_KEY_FILE | string | — | Path to PEM PKCS#8 ECDSA P-256 private key file for signing license tokens in the license-reload test suite. Leave empty when not running license tests. |
TESTER_ADMIN_KEY_FILE | string | — | Path to Ed25519 private key file for admin JWT signing. When unset, an ephemeral keypair is generated per test run (local dev only). |
TESTER_ADMIN_KEY_ID | string | bootstrap-0 | Key ID embedded in admin JWTs; must match the kid registered with the provisioning service. |
TESTER_PUSH_RECEIVER_HOST | string | — | Hostname the push service uses to reach the tester's mock WebPush receiver for delivery verification. Empty skips the delivery check. |
TESTER_PUSH_RECEIVER_PORT | int | 8095 | Port the tester's mock WebPush receiver listens on for push delivery verification. |
TESTER_JWT_LIFETIME | time.Duration | 15m | Lifetime of JWTs issued by the tester. Must be positive and greater than TESTER_JWT_REFRESH_BEFORE. |
TESTER_JWT_REFRESH_BEFORE | time.Duration | 2m | How early before JWT expiry the tester proactively refreshes tokens to avoid auth gaps during long-running tests. |
TESTER_KEY_EXPIRY | time.Duration | 24h | Lifetime of API keys created by the tester for test runs. Must be >= TESTER_JWT_LIFETIME. |
TESTER_AUTH_MODE | runner.AuthMode | jwt | Credential mode for WebSocket connections: jwt, api-key, upgrade (JWT → API key), or mixed (ratio-split). |
TESTER_API_KEY | string | — | Pre-provisioned static API key for api-key, upgrade, and mixed auth modes. Required when TESTER_AUTH_MODE is api-key or upgrade. |
TESTER_AUTH_MIX_RATIO | float64 | 0.5 | Fraction of connections using JWT in mixed mode (0.0 = all API key, 1.0 = all JWT). |
TESTER_AUTH_UPGRADE_TIMEOUT | time.Duration | 10s | Timeout for the JWT-to-API-key upgrade handshake in upgrade mode. |
TESTER_GATEWAY_METRICS_URL | string | — | Prometheus metrics endpoint of the gateway pod. When empty, metric-drift checks in revocation suites are skipped (recorded as skipped_checks, not failures). |
TESTER_GATEWAY_METRICS_INTERVAL | time.Duration | 30s | Interval for polling gateway Prometheus metrics during revocation load tests. |
TESTER_WEBHOOK_BASE_URL | string | — | Base URL the webhook-worker uses to deliver webhooks to this tester pod (e.g. http://tester.sukko-ci.svc.cluster.local:8085). When empty, the webhooks suite is skipped. |
TESTER_WEBHOOK_DELIVERY_TIMEOUT | time.Duration | 15s | Maximum time to wait for the initial webhook delivery after triggering a test delivery. |
TESTER_WEBHOOK_RETRY_TIMEOUT | time.Duration | 30s | Maximum time to wait for the final retry to arrive after triggering a retry test. |