Atlantis at Scale
Scaling Atlantis requires manual operational work like Redis-based locking and object storage, pushing many teams toward managed alternatives like Spacelift.
Deep dive
- Atlantis Architecture Limits: Single-replica StatefulSets struggle with concurrent PRs, leading to queueing and saturation.
- Scaling Hurdles: Horizontal scaling requires complex add-ons like Redis and S3; caching Terraform providers conflicts with concurrency requirements.
- Missing Enterprise Features: Lacks native project dependency graphs, real RBAC, and automated drift remediation without custom code.
- Spacelift Advantages: Provides OPA-based policy-as-code, native dependency management, and built-in audit trails.
Decoder
- Drift: When the actual state of cloud infrastructure deviates from the configuration files defined in Terraform due to manual changes in a console.
- DAG: Directed Acyclic Graph, a structure used to define the order of execution where one task depends on the output of another without forming infinite loops.
Original article
Atlantis at Scale: How It Works and Where It Breaks
Atlantis is the tool of choice when engineers run terraform apply from their laptops. You drop a server in your network, wire up webhooks, and then your infrastructure changes are applied via pull requests like normal code.
That story holds up really well for a while, but when your organization grows, your repo count expands, and multiple people open PRs at the same time, things start feeling slow and fragile. In this article, we will walk through what Atlantis is, where it starts to break as you scale, what a serious production deployment looks like, and when it makes sense to move to something else.
What is Atlantis?
Atlantis is an open-source tool that automates Terraform through pull requests. It is a single GO binary that listens for webhooks from your Git provider, runs Terraform commands, and posts the output back as a comment on the PR.
The process is simple and easy to follow:
- You modify your Terraform files and open a pull request.
- Once the pull request is open, Atlantis receives a webhook, clones the repo, and runs terraform plan.
- The plan output appears as a comment on your PR.
- A reviewer approves, someone comments
atlantis apply, and Atlantis runs the apply. - The PR merges, and Atlantis unlocks the project.
The Atlantis adoption is really simple, as everything happens where your team already works. You don’t need to learn a new UI; just read a comment and type another one.
Atlantis architecture overview at scale
Of the many ways to deploy Atlantis, the most common is Kubernetes. By default, Atlantis has no external database and stores plan files on the local disk. The official Kubernetes manifests use a StatefulSet with replicas: 1 and a persistent volume.
So, the Atlantis architecture has:
- One HTTP server that accepts webhooks and serves a small web UI
- A working directory on disk where every repo gets cloned per PR and workspace
- A locking layer that helps prevent two PRs from planning or applying to the same project at the same time.
- Terraform binaries that Atlantis uses to download and execute as subprocesses on the same machine
Where Atlantis breaks down at scale
1. The single server becomes a queue
Atlantis runs every clone, plan, and apply as a subprocess on the machine that received the webhook. That is fine when two people are working. It stops being fine when your monorepo has 70 projects and a PR touches a shared module because autoplan fires for every affected project. Multiply that by four open PRs and the worker pool is saturated.
2. Vertical scaling is the only straightforward lever you have
The obvious fix is a bigger box, and it works for a while. You add CPU and memory and then raise --parallel-pool-size, which controls how many plans and applies run at once and defaults to 15 on a single machine. The catch is what actually saturates first. Teams end up on very large instances with the CPU mostly idle and the disk thrashing on git clones and provider downloads.
3. You can scale horizontally, but you have to opt into it
By default, Atlantis stores locks in an embedded database only one process can open. Switching to --locking-db-type=redis lets several replicas share lock state. Plan files still sit on local disk, so you must enable --enable-external-stores to upload plans to an S3-compatible bucket.
4. Provider and module downloads dominate runtime
Every run gets a fresh working directory per PR and workspace, so terraform init runs again and providers download again. Atlantis does cache plugins by default, but the documentation recommends turning that cache off when several projects plan and apply in the same PR because Terraform has a known race condition on a shared cache directory. The two things you want most under load, parallelism and caching, pull against each other.
5. Access control is too limited
Atlantis gives you two ways to decide who can run what: --gh-team-allowlist or an external authorization command. That script is a piece of production access control that you write, test, and maintain forever. The product has no roles, no environments, and no per-account model.
6. Every credential ends up on the same box
If Atlantis manages infrastructure across ten AWS accounts, that one server holds access to all ten. It is the most privileged machine you run, the one with the widest blast radius if someone compromises it.
7. There is a simple alpha version of drift detection
Atlantis only sees the changes that arrive through a PR. As of v0.45.0 there is an alpha drift API, but you don’t get a scheduler. Something outside Atlantis has to call that endpoint on a cadence, and you own it.
8. No dependency graph across projects
If your networking stack has to be applied before your EKS stack, Atlantis will not enforce that. Across PRs and repositories there is nothing. No graph, no shared outputs, no way to declare that one project depends on another.
9. Visibility is limited to PR comments
After the PR closes, your audit trail is a set of comments spread across repos. There is no central run history, no searchable log store, and no per-team dashboard unless you build one and keep it running.
How to deploy Atlantis at scale
- Decide centrally, not per repo: Point the server to a central repo config with
--repo-configand set your defaults there. - Cache your provider downloads: Set a plugin cache directory and back it with persistent storage.
- Set concurrency based on reality: Raising
--parallel-pool-sizewithout adding CPU and memory simply moves the queue rather than removing it. - Turn off the dangerous shortcuts: Use
--disable-apply-allto force engineers to name the specific project they are applying. - Watch what triggers a plan: Tighten your autoplan file patterns so a docs change doesn’t trigger 20 runs.
- Keep the disk on Kubernetes: Plans live on local disk, so the official manifests use a StatefulSet with a persistent volume.
Why use Spacelift as an Atlantis alternative
Spacelift is an alternative to Atlantis because it offers the same PR workflow while providing enterprise-grade orchestration.
- Policy as code with OPA: Control what resources users can create, approval requirements, and notification logic.
- Built-in drift detection: Understand changes made to stacks on a defined schedule without managing external infrastructure.
- Stack dependencies: Create a directed acyclic graph between configurations and share outputs between them.
- Real RBAC and SSO: Native integration with SAML 2.0 for fine-grained access control.
- Full run history and audit trail: Centralized logs and history instead of comments scattered across PRs.
- Private worker pools: Run infrastructure tasks inside your network for security and isolation.
How to migrate from Atlantis to Spacelift
- Each Atlantis project needs its own stack: Define them with the Spacelift Terraform provider so the setup is versioned.
- Import your state: Import your existing state file or continue using your existing S3 backend.
- Move your credentials: Swap static cloud credentials for Spacelift’s managed cloud integrations.
- Translate your rules into policies: Convert
apply_requirementsinto approval policies. - Run both in parallel briefly: Point a few low-risk stacks at Spacelift and compare results before full migration.
- Turn off Atlantis: Gradually disable webhooks and decommission the server.
Key takeaways
Atlantis is an excellent tool with a simple design: one server, local disk, and PR comments as the interface. Its limits are structural: single-server execution, disk-bound plan files, coarse permissions, no enterprise-ready drift detection, and no dependency graph. You should always measure the real cost before deciding to use Atlantis, as plan latency and platform engineering hours matter far more than the instance bill.
Fresh dev news, AI-digested daily. Never miss a trend at devoured.fyi