- name
- 12-factor-apps
- description
- Perform 12-Factor App compliance analysis on any codebase. Use when evaluating application architecture, auditing SaaS applications, or reviewing cloud-native applications against the original 12-Factor methodology.
# 12-Factor App Compliance Analysis
> Reference: [The Twelve-Factor App](https://12factor.net)
## Overview
The 12-Factor App methodology is a set of best practices for building Software-as-a-Service applications that are:
- Portable across execution environments
- Scalable without architectural changes
- Suitable for continuous deployment
- Maintainable with minimal friction
## Input Parameters
| Parameter | Description | Required |
|-----------|-------------|----------|
| `codebase_path` | Root path of the codebase to analyze | Required |
## Analysis Framework
### Factor I: Codebase
**Principle:** One codebase tracked in revision control, many deploys.
**Search Patterns:**
```bash
# Check for version control
ls -la .git 2>/dev/null || ls -la .hg 2>/dev/null
# Check for multiple apps sharing codebase
find . -name "package.json" -o -name "pyproject.toml" -o -name "setup.py" | head -20
# Check for environment-specific code branches
grep -r "if.*production\|if.*development\|if.*staging" --include="*.py" --include="*.js" --include="*.ts"
```
**File Patterns:** `.git/`, `package.json`, `pyproject.toml`, deployment configs
**Compliance Criteria:**
| Level | Criteria |
|-------|----------|
| **Strong** | Single Git repo, same codebase for all environments, no env-specific code branches |
| **Partial** | Single repo but some environment-specific code paths |
| **Weak** | Multiple repos for same app or significant code duplication across environments |
**Anti-patterns:**
- Multiple Git repositories for the same application
- Environment-specific code branches (`if production: ...`)
- Different source files for dev vs prod
- Shared code not extracted to libraries
---
### Factor II: Dependencies
**Principle:** Explicitly declare and isolate dependencies.
**Search Patterns:**
```bash
# Python dependency files
find . -name "requirements.txt" -o -name "pyproject.toml" -o -name "setup.py" -o -name "Pipfile" -o -name "uv.lock"
# JavaScript/TypeScript dependency files
find . -name "package.json" -o -name "package-lock.json" -o -name "yarn.lock" -o -name "pnpm-lock.yaml"
# Check for system tool assumptions
grep -r "subprocess.*curl\|subprocess.*wget\|os.system.*ffmpeg\|shutil.which" --include="*.py"
grep -r "exec.*curl\|child_process.*curl" --include="*.js" --include="*.ts"
# Docker/container isolation
find . -name "Dockerfile" -o -name "docker-compose*.yml"
```
**File Patterns:** `**/requirements*.txt`, `**/package.json`, `**/*.lock`, `**/Dockerfile`
**Compliance Criteria:**
| Level | Criteria |
|-------|----------|
| **Strong** | Lock files present, dependency isolation (venv/Docker), no implicit system tools |
| **Partial** | Dependencies declared but no lock files or isolation |
| **Weak** | Dependencies in documentation only, relies on system-installed packages |
**Anti-patterns:**
- Missing lock files (non-deterministic builds)
- Assuming system tools (curl, ImageMagick, ffmpeg) are available
- Different dependency managers in dev vs production
- No virtual environment or container isolation
---
### Factor III: Config
**Principle:** Store config in the environment.
**Search Patterns:**
```bash
# Environment variable usage
grep -r "os.environ\|os.getenv\|process.env\|ENV\[" --include="*.py" --include="*.js" --include="*.ts" --include="*.rb"
# Hardcoded credentials (anti-pattern)
grep -r "password.*=.*['\"]" --include="*.py" --include="*.js" --include="*.ts" | grep -v "test\|spec\|example"
grep -r "api_key.*=.*['\"]" --include="*.py" --include="*.js" --include="*.ts" | grep -v "test\|spec\|example"
grep -r "secret.*=.*['\"]" --include="*.py" --include="*.js" --include="*.ts" | grep -v "test\|spec\|example"
# Environment-specific config files (anti-pattern)
find . -name "config.dev.*" -o -name "config.prod.*" -o -name "settings.development.*" -o -name "settings.production.*"
# Database URLs in code
grep -r "postgresql://\|mysql://\|mongodb://\|redis://" --include="*.py" --include="*.js" --include="*.ts" | grep -v ".env\|test\|example"
```
**File Patterns:** `**/.env*`, `**/config/*.py`, `**/settings.py`, environment files
**Compliance Criteria:**
| Level | Criteria |
|-------|----------|
| **Strong** | All config via environment variables, no hardcoded secrets, could open-source without leaks |
| **Partial** | Most config externalized but some hardcoded defaults |
| **Weak** | Hardcoded credentials, environment-specific config files |
**Anti-patterns:**
- Hardcoded database URLs, API keys, passwords in source
- Config files like `config/production.yml` vs `config/development.yml`
- Environment grouping (`if ENV == 'production': ...`)
- Secrets committed to version control
---
### Factor IV: Backing Services
**Principle:** Treat backing services as attached resources.
**Search Patterns:**
```bash
# Database connection via config
grep -r "DATABASE_URL\|DB_HOST\|REDIS_URL\|CACHE_URL" --include="*.py" --include="*.js" --include="*.ts"
# Service initialization
grep -r "create_engine\|MongoClient\|Redis\|Celery\|boto3" --include="*.py"
grep -r "createPool\|createClient\|new Redis\|S3Client" --include="*.js" --include="*.ts"
# Hardcoded service locations (anti-pattern)
grep -r "localhost:5432\|localhost:6379\|localhost:27017\|127.0.0.1" --include="*.py" --include="*.js" --include="*.ts" | grep -v "test\|spec\|example\|default"
```
**File Patterns:** `**/database/*.py`, `**/services/*.py`, `**/db.py`, connection configurations
**Compliance Criteria:**
| Level | Criteria |
|-------|----------|
| **Strong** | All services via URL/connection string in config, swappable without code changes |
| **Partial** | Most services configurable but some hardcoded defaults |
| **Weak** | Hardcoded service locations, different code paths per environment |
**Anti-patterns:**
- Hardcoded `localhost` for services in production code
- Conditional logic for local vs cloud services (`if USE_S3: ... else: local_storage`)
- Service-specific code paths based on environment
- Different drivers for dev vs prod
---
### Factor V: Build, Release, Run
**Principle:** Strictly separate build and run stages.
**Search Patterns:**
```bash
# Build/deploy configuration
find . -name "Dockerfile" -o -name "Makefile" -o -name "build.sh" -o -name "deploy.sh"
find . -name ".github/workflows/*.yml" -o -name ".gitlab-ci.yml" -o -name "Jenkinsfile"
# Build scripts in package.json
grep -A5 '"scripts"' package.json 2>/dev/null | grep -E "build|start|deploy"
# Check for runtime compilation (anti-pattern)
grep -r "compile\|transpile\|webpack" --include="*.py" | grep -v "test\|build"
```
**File Patterns:** `**/Dockerfile`, `**/Makefile`, `**/.github/workflows/**`, CI/CD configs
**Compliance Criteria:**
| Level | Criteria |
|-------|----------|
| **Strong** | Immutable releases, clear build/release/run stages, unique release IDs |
| **Partial** | Build and run separated but release not immutable |
| **Weak** | Runtime code modifications, asset compilation at startup |
**Anti-patterns:**
- Runtime code modifications
- Asset compilation during application startup
- Configuration baked into build artifacts
- No release versioning
---
### Factor VI: Processes
**Principle:** Execute the app as one or more stateless processes.
**Search Patterns:**
```bash
# Session storage patterns
grep -r "session\|Session" --include="*.py" --include="*.js" --include="*.ts" | head -20
# In-process state (anti-pattern)
grep -r "global.*cache\|process_local\|instance_cache" --include="*.py"
grep -r "global\..*=\|module\.exports\.cache" --include="*.js" --include="*.ts"
# External session stores (good pattern)
grep -r "redis.*session\|memcached.*session\|session.*redis" --include="*.py" --include="*.js" --include="*.ts"
# Sticky session configuration (anti-pattern)
grep -r "sticky.*session\|session.*affinity" --include="*.yml" --include="*.yaml" --include="*.json"
```
**File Patterns:** `**/middleware/*.py`, `**/session/*.py`, server configurations
**Compliance Criteria:**
| Level | Criteria |
|-------|----------|
| **Strong** | Stateless processes, all state in external datastores (Redis, DB) |
| **Partial** | Mostly stateless but some in-process caching |
| **Weak** | Sticky sessions, in-process session storage, shared memory state |
**Anti-patterns:**
- In-process session storage (`user_sessions = {}`)
- Sticky sessions or session affinity
- File-based caching between requests
- Global mutable state shared across requests
---
### Factor VII: Port Binding
**Principle:** Export services via port binding.
**Search Patterns:**
```bash
# Self-contained port binding
grep -r "app.run\|server.listen\|serve\|uvicorn" --include="*.py"
grep -r "app.listen\|server.listen\|createServer" --include="*.js" --include="*.ts"
# PORT environment variable
grep -r "PORT\|port" --include="*.py" --include="*.js" --include="*.ts" | grep -i "environ\|process.env"
# Webserver as dependency
View on GitHub