Atlantide¶
Typed, deterministic Infrastructure-as-Code for Python.
Write infrastructure in real Python, checked by your IDE and by mypy rather than
by a templating language. In return you get the guarantee a config language exists
to provide: the same config always produces the same plan, and the engine can
demonstrate it.
pip install atlantide # or: uv add atlantide
Python 3.11 or newer. A standalone binary that needs no Python is published with every release — see Installation.
Quickstart¶
atlantide init scaffolds a working project. The default minimal template uses
the local provider, so it applies with no cloud credentials at all:
mkdir demo && cd demo
atlantide init
created demo/.gitignore
created demo/atlantide.toml
created demo/infra.py
ok infra.py — 1 resource(s), no cycles
next: atlantide plan
atlantide apply -y # create it
atlantide plan # again: unchanged
+ create local.File:greeting
Plan: 1 to add
...
Applied: 1 to add (0.0s)
= noop local.File:greeting
Plan: 1 unchanged
That second plan is the engine reading recorded hashes and matching them
against the ones it just computed — no provider was called. atlantide init
--template aws scaffolds the same project against AWS instead.
A quick look¶
from atlantide.core import Stack, output
from atlantide.policy import enforce
from atlantide.providers.aws import S3Bucket, SqsQueue
enforce("require-tags", keys=["env"])
enforce("deny-destroy-in-protected", stacks=["prod"])
for env in ["dev", "prod"]:
with Stack(env, region="eu-north-1", name_prefix="atlantide", tags={"env": env}):
assets = S3Bucket("assets", versioning=(env == "prod"))
jobs = SqsQueue("jobs", fifo=True)
output("assets_arn", assets.arn)
atlantide plan infra.py # preview
atlantide apply infra.py # reconcile, in parallel
atlantide apply infra.py # again: all NOOP, zero provider calls
Reading another resource's output, such as assets.arn, returns a lazy Ref
rather than a value. That read is what creates the dependency edge; there are no
depends_on declarations and no string addresses to keep in sync. The Ref
resolves to the real value at apply time.
Three ideas¶
Enforced determinism. Configs are plain Python, but they are executed by Atlas-lang: a bounded interpreter with no clock, no randomness, no environment and no network. Two runs of the same config produce a byte-identical intermediate representation and the same content hash. This is not a convention that authors must observe — the interpreter provides no way to do otherwise.
Graph state with Merkle skip. Resources form a dependency graph, and each node carries a hash of its own inputs combined with its dependencies' hashes. Apply skips any node whose hash is unchanged without making a single provider call, and reconciles independent nodes in parallel.
Per-field mutability. Every field is declared mutable(), immutable() or
computed(). Changing a mutable field produces an in-place update; changing an
immutable one produces a replacement; computed fields never contribute to a diff.
What a change will cost is visible in the type, before anything runs.
The pipeline¶
Every plan and apply runs one pipeline. Everything before the diff is pure and
deterministic; everything after it touches the world.
Because the first half performs no I/O, plan needs no credentials, validate
is cheap enough for a pre-commit hook, and one compiled artifact can be promoted
from staging to production without the config being executed a second time.
Where to start¶
- Installation — the standalone binary, or the PyPI package.
- Coming from Terraform — the vocabulary mapping, the real differences, and where atlantide is behind.
- How it works — the mental model, followed by a hands-on walkthrough that needs no AWS account.
- Building on AWS — a real multi-environment stack built one resource at a time: VPC, S3, SQS, IAM, Lambda, secrets and policies.
- CLI — every command, targeting, exit codes.
- Authoring — stacks, outputs, lifecycle, secrets, and what config may not do.
- Configuration —
atlantide.toml, inputs, profiles. - Policies — the built-in rules, levels, bindings.
- Remote state — S3 and Postgres backends, locking.
- Troubleshooting — every error, by stage.
- Glossary — the vocabulary, in pipeline order.