Build infrastructure the way nature builds matter
EIF is a provider-agnostic Terraform library that models infrastructure with the elegance of chemistry. Compose atoms into molecules, molecules into matter — on any cloud provider.
uv run eif render matters/three-tier-app/aws devFounding principles
Modern cloud infrastructure suffers from two opposite extremes: the monolith temptation — a single Terraform repository that holds everything — and the chaotic fragmentation of disconnected modules. EIF proposes a third way, inspired by chemistry: every cloud resource has its own atomic identity, composable with precision into increasingly complex structures, up to fully deployable applications.
"Build infrastructure the way nature builds matter — atom by atom,
molecule by molecule, until complexity emerges from simplicity."
The compositional model
Each level builds on the previous. Atoms and molecules are internal building blocks — they are never deployed directly. Matter is the only user-facing level, the sole entry point for every deployment.
LEVEL 01 — ATOM
A single cloud service in plain HCL. The primitive building block of the framework — scoped to one service only. Namespaced by cloud. Atoms are composed by molecules and are never deployed directly.
LEVEL 02 — MOLECULE
A reusable architectural blueprint that combines atoms into a coherent pattern. Molecules are composed by matter and are never deployed directly.
LEVEL 03 — MATTER
A complete application composed of molecules. Structure is declared once in composition.json; each <env>.json is a flat pool of variables — no per-molecule grouping, no repeated environment key (injected automatically). The template is the wiring layer.
Cloud agnostic
Each cloud provider is a self-contained directory. Adding support for a new cloud
requires no changes to eif.py — just drop a template in the right place.
providers/ ├── aws/ │ └── provider.tf.j2 # terraform{} + provider "aws" — profile or assume_role ├── azure/ │ └── provider.tf.j2 # terraform{} + provider "azurerm" — subscription + tenant └── gcp/ └── provider.tf.j2 # terraform{} + provider "google" — project + region
The accounts.json entry declares "provider": "aws" (or azure, gcp).
eif render resolves the right template, renders it with account config as context,
and injects the result as {{ provider_block }} into the matter template.
To contribute a new provider: create providers/<cloud>/provider.tf.j2,
add atoms under atoms/<cloud>/ and molecules under molecules/<cloud>/.
Stability guarantee
Atoms and molecules evolve without breaking existing deployments. Every breaking change creates a new version directory alongside the old one — matter in production stays pinned forever.
Bug fix or new optional variable → edit in place within the existing version.
Breaking change → create a new version directory alongside the old one.
atoms/aws/storage/s3/v1/ ← prod matter stays pinned here
atoms/aws/storage/s3/v2/ ← new feature, new interface
# upgrade a matter composition to latest molecule versions uv run eif upgrade matters/three-tier-app/aws dev # [eif] upgraded "molecules/aws/single-page-application/v1" → "molecules/aws/single-page-application/v2" # [eif] up-to-date "molecules/aws/db/v1" # [eif] wrote → matters/three-tier-app/aws/composition.json
Developer experience
The eif new commands interactively scaffold new atoms, molecules, and matters.
They detect available providers, check for existing versions, and emit starter files
with the correct structure — so you can focus on the implementation, not the boilerplate.
# scaffold a new atom — prompts: name, provider, category uv run eif new atom name: cdn-origin provider: 1) aws 2) azure 3) gcp → 1 category: 1) compute 2) networking 3) storage 4) security 5) other → 2 [eif] atoms/aws/networking/cdn-origin — no existing versions, creating v1 [eif] created atoms/aws/networking/cdn-origin/v1/main.tf [eif] created atoms/aws/networking/cdn-origin/v1/variables.tf [eif] created atoms/aws/networking/cdn-origin/v1/outputs.tf # scaffold a new molecule — prompts: name, provider uv run eif new molecule my-service # scaffold a new matter — prompts: name, provider uv run eif new matter serverless-api [eif] created matters/serverless-api/aws/composition.json [eif] created matters/serverless-api/aws/dev.example.json [eif] created matters/serverless-api/aws/prod.example.json [eif] created matters/serverless-api/aws/main.tf.j2
If an atom or molecule already exists, the command reports the latest version
and asks whether to create the next one — v1 → v2 — preserving all existing deployments.
Providers are auto-detected from the providers/ directory —
no hardcoded list, no config needed.
Repository layout
The repository is organized to faithfully mirror the model hierarchy. Each directory is self-contained and follows a consistent naming convention.
eif/ │ ├── accounts.json # env → cloud account config ├── eif.py # renderer + upgrade + scaffold CLI ├── pyproject.toml # Python project (uv / hatchling) │ ├── providers/ # Pluggable cloud provider templates │ ├── aws/provider.tf.j2 │ ├── azure/provider.tf.j2 │ └── gcp/provider.tf.j2 │ ├── atoms/ # Atomic cloud services — namespaced + versioned │ ├── aws/ │ │ ├── compute/lambda/v1/ │ │ ├── networking/cloudfront/v1/ │ │ ├── storage/s3/v1/ · storage/rds/v1/ │ │ └── security/waf/v1/ · security/sg/v1/ │ ├── azure/ │ │ ├── storage/blob/v1/ │ │ └── networking/frontdoor/v1/ │ └── gcp/ │ ├── storage/gcs/v1/ │ ├── networking/cdn/v1/ │ └── security/armor/v1/ │ ├── molecules/ # Blueprints — namespaced + versioned │ ├── aws/ │ │ ├── single-page-application/v1/ # s3 + cloudfront + waf │ │ ├── db/v1/ # rds + sg │ │ └── lambda-svc/v1/ # lambda + sg │ ├── azure/ │ │ └── single-page-application/v1/ # blob + frontdoor │ └── gcp/ │ └── single-page-application/v1/ # gcs + cdn + armor │ └── matters/ # Deployable applications ├── three-tier-app/ │ └── aws/ │ ├── composition.json # molecule list + pinned versions │ ├── dev.json · test.json · prod.json │ └── main.tf.j2 └── single-page-application/ ├── aws/ ├── azure/ └── gcp/