Signal Forge ADR-006: Fail-fast on missing secrets
Status: Accepted
Decision: Services throw at startup if required connection strings are absent or empty. No fallback to defaults.
Code pattern (.NET):
var connStr = builder.Configuration.GetConnectionString("DefaultConnection");
if (string.IsNullOrWhiteSpace(connStr))
throw new InvalidOperationException(
"ConnectionStrings:DefaultConnection is required. Set the environment variable.");
Rationale:
- A service that starts without a database connection appears healthy to liveness probes but fails all requests. This is worse than failing loudly at startup — it makes root cause harder to find.
- Fail-fast produces a clear error in pod logs immediately, the pod enters
CrashLoopBackOff, and the operator can read the exact missing variable fromkubectl describe pod. - Silent defaults (e.g. connecting to
localhost:3306) work in developer machines but break in Kubernetes where there is no local database — this class of environment-specific bugs is eliminated.
Alternative considered: Fallback defaults — rejected because they hide misconfiguration.
This complements secretKeyRef for all credentials: that ADR governs how credentials are stored and referenced; this one governs what happens when a required one is absent.
Local graph
Linked from 2 notes
Resilience patterns
Application-level failure handling in Signal Forge: retries, circuit breakers, backoff, and delivery-safety patterns for downstream dependency failures.
Signal Forge ADR-007: secretKeyRef for all credentials (no plaintext env vars)
Stores all database, RabbitMQ, and API credentials in Kubernetes Secrets referenced via secretKeyRef so manifests stay safe to commit.
Related notes
Signal Forge ADR-005: Separate collector configmaps per deployment mode
Keeps cloud and local Alloy collector configs in separate files rather than one conditional configmap, so each mode's exporters stay explicit and uncoupled.
Signal Forge ADR-003: Span metrics generated before tail sampling
Places the spanmetrics connector ahead of tail_sampling so RED metrics reflect all traffic instead of only the ~25% of traces that survive sampling.
Signal Forge ADR-002: SpanLink for async RabbitMQ propagation (not parent-child)
Uses a SpanLink, not a parent-child span relationship, to connect RabbitMQ consumer spans back to the producer span across async, retry-prone delivery.
Architecture Overview
Signal Forge's topology, service communication, trace propagation, and per-signal pipeline flow across local and Grafana Cloud deployment modes.