12-Factor App Compliance
Snackbox aims to be fully compliant with the 12-factor app methodology. The 12-factor principles guide the design towards portable, self-contained, and operationally simple services — which aligns directly with the Snackbox goal of being easy to deploy and operate at scale.
This document records the current compliance state and known gaps.
Evaluation
| # | Factor | Status | Notes |
|---|---|---|---|
| 1 | Codebase | ✅ | Single Git repository on GitLab; one codebase deployed to multiple targets (systemd, Docker) |
| 2 | Dependencies | ✅ | All dependencies declared in go.mod + go.sum; go mod download in CI; static binary bundles everything at build time |
| 3 | Config | ✅ | All runtime configuration via environment variables (internal/config); optional .env file as a developer convenience, never baked into the binary |
| 4 | Backing services | ⚠️ | SQLite is embedded — not an attachable network resource. Media files are also local-only. Single-host deployments are unaffected; horizontal scaling and Kubernetes require the planned MariaDB + S3 backends (2.0.0) |
| 5 | Build, release, run | ✅ | Multi-stage Dockerfile cleanly separates build and runtime. CI has distinct build → release stages. The binary is immutable once built |
| 6 | Processes | ⚠️ | Mostly stateless — JWT is validated per-request with no server-side sessions. The rate-limiter holds per-IP state in memory; this state is lost on restart and differs across replicas |
| 7 | Port binding | ✅ | Self-contained HTTP server on configurable LISTEN_ADDR; no external app server required at runtime |
| 8 | Concurrency | ⚠️ | Go's goroutine-per-request model handles concurrent reads well. Write concurrency is bounded by SQLite's single-writer lock; horizontal scaling past one instance is not practical without the MariaDB backend (2.0.0) |
| 9 | Disposability | ✅ | SIGTERM triggers graceful shutdown: in-flight requests drain within SHUTDOWN_TIMEOUT (default 15 s), then the process exits cleanly |
| 10 | Dev/prod parity | ✅ | Same binary and Docker image in all environments; .env.example keeps local config close to production defaults; no dev-only dependencies or code paths |
| 11 | Logs | ✅ | All output written to stdout via the standard library logger; no log files or rotation. Aggregation is left to the operator (journald, Docker log driver, Loki, etc.) |
| 12 | Admin processes | ⚠️ | Migrations and initial admin user creation run automatically at startup rather than as an explicit one-off command. Pragmatic for the current scale; a dedicated snackbox migrate subcommand would be more strictly correct |
Summary
Fully compliant (8 / 12): Codebase, Dependencies, Config, Build/release/run, Port binding, Disposability, Dev/prod parity, Logs.
Partially compliant (4 / 12):
| Gap | Resolution |
|---|---|
| Backing services (IV) | MariaDB + S3 media backends planned for 2.0.0 |
| Processes (VI) | In-memory rate-limiter state; acceptable for single-instance, breaks with replicas |
| Concurrency (VIII) | Resolves together with MariaDB backend (2.0.0) |
| Admin processes (XII) | Startup-time migration is pragmatic; low priority to change |