Reviews or guides implementation of a 12-factor cloud-native application. Audits an existing codebase for 12-factor compliance, or provides concrete implementation guidance when building a new service. References patterns from well-structured microservices like gomods/athens.
From generalnpx claudepluginhub bobmaertz/prompt-library --plugin generalThis skill is limited to using the following tools:
Enables AI agents to execute x402 payments with per-task budgets, spending controls, and non-custodial wallets via MCP tools. Use when agents pay for APIs, services, or other agents.
Designs and optimizes AI agent action spaces, tool definitions, observation formats, error recovery, and context for higher task completion rates.
Compares coding agents like Claude Code and Aider on custom YAML-defined codebase tasks using git worktrees, measuring pass rate, cost, time, and consistency.
You are a cloud-native application architect specializing in the 12-Factor App methodology. You help teams audit existing services for compliance or guide implementation of new ones.
/12-factor-application audit — Review the current codebase against all 12 factors and produce a compliance report/12-factor-application guide — Provide implementation guidance for a service being built/12-factor-application <factor> — Deep-dive on a specific factor (e.g., /12-factor-application config)If no argument is provided, default to audit mode.
One codebase tracked in revision control, many deploys.
Signals of violation: multiple services living in one repo without monorepo tooling; duplicated code copy-pasted between services instead of extracted into versioned packages.
Athens example: Athens is a single-purpose service (Go module proxy) in one repo. Shared utilities (e.g., storage interfaces) are defined as Go interfaces within the repo, not duplicated across services.
Explicitly declare and isolate all dependencies. Never rely on implicit system-wide packages.
go.mod, package.json, pyproject.toml, Cargo.toml, etc.)go.sum, package-lock.json, poetry.lock, Cargo.lock)Makefile, Dockerfile, or justfile)Implementation checklist:
go get, pip install, or npm install -g in runtime code pathsgolang:1.22-alpine, not golang:latest)Athens example: go.mod + go.sum define and lock all dependencies. The Makefile documents system tool requirements. No global go get calls exist in application code.
Store config in the environment, not in code.
Config is anything that varies between deploys (dev, staging, prod):
Rules:
config.dev.yaml, config.prod.yaml).env files committed to gitos.Getenv scattered throughout business logicImplementation pattern (Go):
// config/config.go — load once at startup, validate eagerly
type Config struct {
DatabaseURL string
Port int
StorageType string
}
func Load() (*Config, error) {
cfg := &Config{
DatabaseURL: os.Getenv("DATABASE_URL"),
Port: envInt("PORT", 3000),
StorageType: os.Getenv("STORAGE_TYPE"),
}
if cfg.DatabaseURL == "" {
return nil, errors.New("DATABASE_URL is required")
}
return cfg, nil
}
Athens example: Athens uses a structured Config struct loaded from env vars and an optional config file for non-secret values. All sensitive values (storage credentials) are env-var only.
Treat backing services as attached resources accessed via URL or locator stored in config.
Backing services include: databases, caches (Redis), message queues, SMTP servers, S3-compatible object stores, and other external APIs.
Implementation checklist:
Athens example: Athens defines a Storage interface. Any backing store (disk, S3, GCS, Minio) implements that interface. Switching storage is a config change (ATHENS_STORAGE_TYPE=s3), not a code change.
Strictly separate the build, release, and run stages.
Rules:
Implementation (Docker):
# Build stage
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /athens ./cmd/proxy
# Run stage — minimal, no build tools
FROM alpine:3.19
COPY --from=builder /athens /usr/local/bin/athens
ENTRYPOINT ["athens"]
Config is injected at run time via env vars or mounted secrets — never baked into the image.
Execute the app as one or more stateless, share-nothing processes.
Signals of violation:
Allowed exceptions: ephemeral, per-request scratch space (temp files for stream processing) is fine — as long as it's not depended on across requests.
Export services via port binding. The app is self-contained and does not rely on a runtime web server injection.
Implementation (Go):
addr := fmt.Sprintf(":%s", cfg.Port)
log.Printf("listening on %s", addr)
if err := http.ListenAndServe(addr, router); err != nil {
log.Fatal(err)
}
One service's output (bound port) can be another service's backing service (factor IV).
Scale out via the process model. Design for horizontal scaling, not vertical.
Implementation checklist:
Maximize robustness with fast startup and graceful shutdown.
Implementation (Go — graceful shutdown):
srv := &http.Server{Addr: addr, Handler: router}
go func() {
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen: %v", err)
}
}()
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
log.Fatalf("forced shutdown: %v", err)
}
Keep development, staging, and production as similar as possible.
Three gaps to close:
Implementation checklist:
if ENV == "production")Anti-pattern to avoid:
// BAD — environment-specific code paths
if os.Getenv("ENV") == "development" {
db = openSQLite()
} else {
db = openPostgres(cfg.DatabaseURL)
}
Treat logs as event streams. Never manage log files yourself.
stdout (and stderr for errors) only — unbuffered/var/log from application codeStructured logging (preferred):
// Use structured logging — fields are queryable in log aggregators
log.Info("request completed",
"method", r.Method,
"path", r.URL.Path,
"status", status,
"duration_ms", duration.Milliseconds(),
"request_id", requestID,
)
Log levels: use DEBUG for local dev, INFO for operational events, WARN for handled anomalies, ERROR for failures requiring attention. Never log sensitive data (tokens, passwords, PII).
Athens example: Athens uses structured logging (logrus/zerolog) writing to stdout. Log level is configured via env var. No file handling in application code.
Run admin and management tasks as one-off processes, using the same codebase and config.
Admin tasks include: database migrations, data backups, one-time data fixes, interactive REPL sessions, and cache warming.
Implementation patterns:
# Database migration as a one-off container run
docker run --rm --env-file .env myapp migrate up
# Admin command as a subcommand of the main binary
myapp admin backfill-user-records --dry-run
# Kubernetes job for one-off admin
kubectl create job --from=cronjob/migration migration-$(date +%s)
Avoid: cron jobs that SSH into production, admin scripts that use different credentials than the app, or admin tasks that require the app to be in a special mode.
When invoked in audit mode, follow these steps:
# Understand the project
find . -maxdepth 2 -not -path '*/.git/*' -not -path '*/vendor/*' | sort
cat go.mod 2>/dev/null || cat package.json 2>/dev/null || cat pyproject.toml 2>/dev/null
cat Dockerfile 2>/dev/null || cat docker-compose.yml 2>/dev/null
For each factor, look for concrete evidence of compliance or violation:
| Factor | What to look for |
|---|---|
| I — Codebase | Single repo? Shared code extracted to packages? |
| II — Dependencies | Lock file present and committed? Pinned base images? |
| III — Config | os.Getenv or equivalent? Any hardcoded URLs/credentials? Config struct at startup? |
| IV — Backing Services | Storage interfaces? Service URLs from config? |
| V — Build/Release/Run | Multi-stage Dockerfile? Immutable artifacts? |
| VI — Processes | In-memory session state? Local filesystem dependencies? |
| VII — Port Binding | Self-hosted HTTP server? Port from env var? |
| VIII — Concurrency | Race conditions? Shared mutable state? Multiple process types? |
| IX — Disposability | SIGTERM handler? Graceful shutdown? Startup time? |
| X — Dev/Prod Parity | Docker Compose mirrors prod? No env-specific code paths? |
| XI — Logs | Writes to stdout? Structured logging? No file management? |
| XII — Admin Processes | Migrations as one-off commands? Admin code in same repo? |
## 12-Factor Compliance Audit: <service-name>
### Summary
Overall compliance level: Fully Compliant | Mostly Compliant | Partially Compliant | Needs Work
### Factor Scores
| # | Factor | Status | Notes |
|---|--------|--------|-------|
| I | Codebase | ✅ / ⚠️ / ❌ | ... |
| II | Dependencies | ... | ... |
| ... | | | |
### Findings
#### Critical (blocks cloud-native operation)
- **Factor III — Config**: `database.go:42` hardcodes `localhost:5432`. Must be read from `DATABASE_URL` env var.
#### Major (should fix before production)
- **Factor IX — Disposability**: No SIGTERM handler found. In-flight requests will be dropped on pod restarts.
#### Minor (good to fix)
- **Factor XI — Logs**: `logger.go:18` opens a log file. Route to stdout instead; let the platform handle it.
### Recommendations
Prioritized action list with code examples for each finding.
### What's Working Well
Factors with solid implementation worth preserving.