Designed for the Cloud from Day One

The twelve-factor app methodology defines best practices for building software-as-a-service applications that are portable, scalable, and maintainable across cloud environments. Originally formulated by Heroku engineers, these principles are now the foundation of modern cloud-native development. At Nexis Limited, our SaaS products follow twelve-factor principles.

The Twelve Factors

I. Codebase — One Codebase, Many Deploys

One codebase tracked in version control, deployed to multiple environments (development, staging, production). Different environments run different versions of the same codebase — never different codebases. If multiple services share code, extract it into a library.

II. Dependencies — Explicitly Declare Dependencies

Never rely on system-wide packages. Declare all dependencies explicitly in a manifest file (package.json, requirements.txt, go.mod). Use a dependency isolation tool (npm, pip venv, Go modules) to ensure a clean environment. The application should run on any machine after installing declared dependencies.

III. Config — Store Config in the Environment

Configuration that varies between environments (database URLs, API keys, feature flags) must be stored in environment variables, not in code. Never commit credentials to version control. The same codebase with different environment variables runs in development, staging, and production.

IV. Backing Services — Treat Backing Services as Attached Resources

Databases, message queues, email services, and caches are attached resources accessed via URLs or connection strings from configuration. Swapping a local PostgreSQL database for a managed cloud database should require only a configuration change, not a code change.

V. Build, Release, Run — Strictly Separate Build and Run Stages

The build stage compiles code and bundles dependencies. The release stage combines the build with environment configuration. The run stage executes the application. Each release should have a unique ID and be immutable — never modify a release in place.

VI. Processes — Execute as Stateless Processes

Application processes should be stateless. Any persistent data must be stored in a backing service (database, cache, object storage). Do not store session state, uploaded files, or temporary data in the process memory or local filesystem — these are lost when the process restarts or scales.

VII. Port Binding — Export Services via Port Binding

The application is self-contained and exports an HTTP service by binding to a port. The application does not depend on a web server being injected at runtime. A Node.js app listens on a port directly. A container exposes a port. The routing layer (load balancer, Kubernetes Service) routes traffic to these ports.

VIII. Concurrency — Scale Out via the Process Model

Scale horizontally by running multiple instances of the application, not by increasing the resources of a single instance. Design the application to run as multiple concurrent processes — web processes handle requests, worker processes handle background jobs. Container orchestration (Kubernetes) manages scaling.

IX. Disposability — Maximize Robustness with Fast Startup and Graceful Shutdown

Processes should start quickly and shut down gracefully. Handle SIGTERM by finishing in-flight requests and releasing resources. Fast startup enables rapid scaling and deployment. Graceful shutdown prevents data loss and broken connections.

X. Dev/Prod Parity — Keep Development, Staging, and Production Similar

Minimize the gap between development and production — use the same backing services, the same technology stack, and similar configurations. If production uses PostgreSQL, development should use PostgreSQL, not SQLite. Docker and Docker Compose make this achievable.

XI. Logs — Treat Logs as Event Streams

The application should not manage log file routing or storage. Write logs to stdout. The execution environment captures, aggregates, and routes log streams to monitoring systems (ELK, Datadog, CloudWatch). This separates the application's concerns from log infrastructure.

XII. Admin Processes — Run Admin Tasks as One-Off Processes

Administrative tasks (database migrations, data cleanup scripts) should run as one-off processes using the same codebase and configuration as the application. Run them in the same environment using the same deployment mechanism — not as manual SSH sessions on production servers.

Beyond Twelve Factors

Modern additions to these principles include: API-first design, telemetry and observability, security as a first-class concern, and infrastructure as code. These extend the original twelve factors for today's microservices and Kubernetes-based architectures.

Conclusion

The twelve-factor methodology is a proven foundation for building cloud-native SaaS applications. Following these principles ensures your application is portable, scalable, and maintainable across modern cloud environments. Start with these principles, and your application will be ready for any cloud platform.

Building cloud-native software? Our team architects twelve-factor SaaS applications.