This article outlines the core design principles behind a configuration-driven approach to AWS infrastructure.
These principles are designed to support modularity, auditability, scalability, and low-friction deployment across environments. Together, they form a consistent model that separates infrastructure code, configuration, and runtime behavior—while keeping everything connected through predictable patterns.
If you’re looking to implement infrastructure that supports dynamic environments, feature isolation, and clean service boundaries, these principles provide a framework for building systems that are both flexible and easy to manage.
Why Design Principles Matter
Without a consistent set of principles, infrastructure can quickly become hard to scale, debug, or evolve. This approach is informed by real-world needs—where teams must deliver quickly, isolate environments safely, and maintain visibility into what’s deployed.
The following principles serve as a foundation for building systems that are modular, testable, and production-ready, without compromising control.
Core Design Principles
Build Once, Deploy Anywhere
Terraform modules are reusable across environments and AWS accounts. They don’t include hardcoded values. The same component can be deployed anywhere by providing configuration through AWS Parameter Store.
Configuration Is the Source of Truth
Only components defined in the aws-config
repository are eligible to be deployed. Terraform fails fast if configuration is missing. All changes to infrastructure flow through Git, enabling full visibility and auditability.
Immutable Infrastructure
Infrastructure is never patched in place. Instead, new versions are deployed side by side and swapped in by updating configuration (e.g., updating a runtime parameter to point to a new service version).
Dynamic Dependency Resolution
Services don’t hardcode references to other services. Instead, they resolve dependencies using nicknames and AWS Parameter Store. This allows one service to refer to another dynamically, making replacements and updates seamless.
Separation of Concerns
Infrastructure code, configuration, and application logic are maintained in separate repositories:
aws-iac
: Terraform modulesaws-config
: Configuration (in JSON)aws-lambda
: Application and microservices
Each repo is testable and deployable independently.
Environment-Agnostic Modules
Terraform modules don’t know what environment they’re in. Each module receives a nickname and retrieves its configuration from a path like:
/iac/<component>/<nickname>/config
It writes outputs to:
/iac/<component>/<nickname>/runtime
External System Referencing
Even systems not built within this infrastructure model can be referenced predictably. For example:
/external/databases/legacy-db/runtime
This enables integration with third-party services or legacy stacks using the same patterns.
Git as the Gatekeeper
Nothing is deployed unless it’s defined in Git. All changes require review and approval, supporting clear separation of responsibilities, full history, and strong audit trails.
LocalStack-Compatible by Default
Terraform modules support both AWS and LocalStack. This allows local testing and iteration with near-zero cloud cost, while still supporting full production deployments.
Smart Runtime Caching
Systems may cache configuration data locally for performance. If a failure occurs (e.g., database connection error), the system re-checks AWS Parameter Store before failing—enabling dynamic reconfiguration and fast cutover support.
For more technical details, see the Adage Design Principles reference on GitHub.
Real-World Applications
These principles are already enabling patterns like:
- Running multiple versions of a database in QA to support feature testing
- Deploying services without needing to update consumers
- Referencing external or legacy systems using a unified lookup strategy
- Replacing infrastructure without modifying consumer logic
Explore the Repos
The architecture is publicly available across these GitHub repositories
The Adage guide explains how to use the model: 👉 View on GitHub
This system is built around three Git repositories:
-
Infrastructure as Code (
aws-iac
) 👉 View on GitHub -
Configuration (
aws-config
) 👉 View on GitHub -
Lambda Functions (
aws-lambda
) 👉 View on GitHub
What’s Next?
Future work will include:
- Example architectures built from reusable components
- AppConfig and EventBridge integration for live refresh
- Tools for syncing configuration and validating environment state
Let me know what you think — and if you’re building something similar, I’d love to hear how you’re approaching it.