AWS

AWS LZA vs NTC Deep Dive Part 1: Getting Started, Organization, Accounts and Access

What Day 1 looks like on LZA and NTC, from the first bootstrap to a working multi-account organization with accounts and SSO.

Oct 16, 2026 · 12 min read · 2,404 words

Photo generated by chatGPT

Introduction

After my overview comparison of AWS LZA and Nuvibit NTC, the question I got most was a simple one: "What does Day 1 actually look like?" Not the feature matrix, but what happens when you open a terminal on an empty management account.

I can answer that for both. I ran LZA in production from 2023 on top of Control Tower until I decommissioned it in favor of NTC (more on that in Part 3). I deployed NTC from scratch as part of Nuvibit's partner program, and I kept that test organization up to date until a round of module upgrades in October 2026. So for NTC, I saw Day 1 and most of Day 2.

This series is three parts, in the order you would actually work:

  1. Getting started: bootstrap, organization, accounts and access (this post)
  2. Logging, security and compliance
  3. Day 2 operations and the verdict

Everything below comes from my own organizations. I removed account IDs, e-mail addresses, and bucket names, and kept the examples generic where the details don't matter. Let's dive in.

What you need before you start

Both platforms need a few things in place first, and that already tells you how each one thinks.

LZANTC
FoundationControl Tower first (I run v4.0)AWS Organizations enabled by hand, then imported
SkillsYAML, plus CDK and CloudFormation for anything beyond the built-in optionsOpenTofu/Terraform, Git, GitHub Actions
Configuration lives inOne CodeCommit repository or S3 bucketOne GitHub repository per phase
CredentialsManagement account access, Control Tower rolesOne temporary IAM user, for the bootstrap only
RegionsHome eu-central-1, plus us-east-1Home eu-central-1, plus us-east-1

For LZA, set up Control Tower first. LZA isn't standalone. It sits on top of Control Tower. You can run it on plain AWS Organizations, but Control Tower is the recommended base. So step one is the Control Tower wizard, and you can only start LZA after it creates your Audit and Log Archive accounts. Since LZA v1.15.0, it can also activate Control Tower and those two accounts as part of its own bootstrap.

For NTC, you get invited to a partner GitHub organization that holds one blueprint repository per phase. There are seven, numbered 0 to 6. You work through them in order, and each one has its own state, pipeline, and README. Unlike LZA, it splits into 6 smaller pipelines and states, giving you faster feedback, and teams can also use the repositories separately with fine-grained permissions.

Day 1 with LZA

Control Tower first

In the Control Tower console, click "Set up landing zone" and select the home region and governed regions. I used eu-central-1 as home and added us-east-1. Control Tower then creates a Security OU with the Audit and Log Archive accounts, a Sandbox OU, a first set of SCPs and guardrails, and Identity Center. That alone takes 30-60 minutes.

One repository, one large pipeline

Everything LZA does is described in a single configuration repository:

aws-accelerator-config/
├── accounts-config.yaml        # accounts and e-mail addresses
├── global-config.yaml          # logging, CloudTrail, budgets, regions
├── iam-config.yaml            # IAM roles, Identity Center permission sets
├── network-config.yaml         # VPCs, Transit Gateway, Route 53
├── organization-config.yaml    # OUs, SCPs, tagging policies
├── security-config.yaml        # Security Hub, GuardDuty, Config rules
└── customizations-config.yaml  # custom CloudFormation stacks

I started with global-config.yaml because it holds the settings everything else depends on:

homeRegion: eu-central-1
enabledRegions:
  - eu-central-1
  - us-east-1
managementAccountAccessRole: AWSControlTowerExecution
terminationProtection: true
controlTower:
  enable: true
logging:
  account: LogArchive

managementAccountAccessRole makes LZA reuse the cross-account role Control Tower already created, and terminationProtection is one of those flags you set once and never regret.

After the commit, the pipeline starts automatically: validate, build (CDK synthesizes the CloudFormation templates), then several deploy stages for prepare, accounts, organizations, security, and operations. My first run took about 75 minutes. Later runs take around 40 to 45 minutes, even for a one-line YAML change.

Part 1 of the pipeline:

Part 2:

Part 3:

The upside is that a green pipeline means your configuration is consistent across all seven files. The downside is that you fix a typo, wait 45 minutes, find the next typo, and wait again.

Personally, I prefer fast feedback loops, and this is the part of LZA that never fully convinced me. The aws-luminarlz-cli helps here, because it can run single stages through the LZA core CLI. I would love to see that in LZA itself.

Where you need more than YAML

I expected a YAML-only experience. It holds for the basics, but customizations-config.yaml is where you land as soon as you need more: it points to your own CloudFormation templates, and if you write them as CDK, something like aws-luminarlz-cli synthesizes them first. I'll show a real example in Part 2, because that is where I needed it.

Two limits you hit early

  • Control Tower's Account Factory fails when a pipeline run creates more than about three accounts. There is a comment about it in my accounts-config.yaml. Ten new accounts means at least four pipeline runs.
  • An SCP can only be 5,120 characters long. A comprehensive guardrail policy does not fit, so I run three accelerator guardrail policies side by side instead of one.

Neither is in the getting-started guides. Both are Control Tower and AWS limits that LZA inherits. As an SA, you need to know them.

Day 1 with NTC

Phase 0: the local bootstrap

NTC starts on your machine. Nuvibit invites you to the partner organization, you clone the Phase 0 repository, put temporary credentials of an IAM user into your shell once, and run it:

export AWS_ACCESS_KEY_ID="<key-id>"
export AWS_SECRET_ACCESS_KEY="<secret>"
export AWS_DEFAULT_REGION="eu-central-1"
 
tofu init
tofu apply

It creates the S3 bucket for the remote state for the next phases, the OIDC provider for GitHub Actions, and an IAM role the pipelines assume. It took a few minutes. From that point on, every change goes through GitHub Actions and OIDC, and no long-lived credentials exist anywhere. I love that.

I deactivated the access key and deleted the user. If not, the IAM user would have stayed in the management account with AdministratorAccess and no MFA.

Phase 1: organizations and the parameter bucket

NTC does not create your AWS Organization. You enable it in the console and import it, then into the module:

import {
  to = module.ntc_organizations.aws_organizations_organization.ntc_org
  id = "o-xxxxxxxxxx"
}

I had expected full automation here. The pragmatic reason is that most customers already have an organization, so import is the common path.

The second building block in this phase is NTC Parameters. Cross-phase data (OU IDs, account IDs, bucket ARNs) isn't shared through SSM Parameter Store, which is account-scoped, but through a JSON document in a dedicated S3 bucket, with a reader and a writer module. The bucket and its readers and writers depend on each other, so you deploy in stages.

The OU structure follows the NARA reference architecture and is a plain list of paths:

organizational_unit_paths = [
  "/root/core",
  "/root/sandbox",
  "/root/suspended",
  "/root/transitional",
  "/root/workloads",
  "/root/workloads/prod",
  "/root/workloads/dev",
  "/root/workloads/test"
]

The suspended OU for decommissioned accounts and the transitional OU for accounts you migrate into the organization are things you usually only add after you got burned. I have the same Suspended OU in my LZA organization. Guardrails come from a separate ntc-guardrail-templates module with ready-made SCPs for the root, suspended, and workloads OUs. In LZA, the same job is done by serviceControlPolicies in organization-config.yaml plus your own JSON policies.

Phase 2: the account factory

The account factory has two halves, and it helps to keep them apart in your head:

  • Lifecycle is event-driven (Step Functions and Lambda). It reacts to events like an account being created and, for example, deletes the default VPC or enables opt-in regions.
  • Baseline is stateful (CodePipeline and CodeBuild). It runs inside each member account, applies OIDC, IAM roles, the state backend, and AWS Config, then keeps detecting and correcting drift afterward.

Accounts themselves are plain JSON, separate from the HCL:

{
  "account_name": "log-archive",
  "account_email": "aws-roots+ntc-log-archive-a3f5g6gh8@example.com",
  "ou_path": "/root/core",
  "close_on_deletion": false,
  "account_tags": {
    "AccountType": "core"
  }
}

When something fails here, you look at three places: GitHub Actions for the OpenTofu run, Step Functions for the lifecycle, and CodeBuild for the baselines. That is more surfaces than I like, but each one has a clear job. If you add lifecycle functions later, you also have to trigger the state machine yourself once.

Phase 3: Identity Center

You have to enable Identity Center manually in the console before the phase can run.

After that, deployment was simple. Users and groups are JSON files, and permission sets come with sensible defaults like admin, power user, view only, and billing.

The part I like most is dynamic assignments. They are based on the account map the account factory publishes, so a new account in a given OU gets its permission sets without anyone editing Identity Center. Create an account, wait for the baseline, and the access is there. Phase 3 has one more trick that I cover in Part 3: it is the only phase that triggers another one.

Identity compared

In my LZA organization, identity is small on purpose:

identityCenter:
  delegatedAdminAccount: Audit
  identityCenterPermissionSets:
    - name: AdministratorAccess
      policies:
        awsManaged:
          - arn:aws:iam::aws:policy/AdministratorAccess
      sessionDuration: 600
    - name: BillingReviewer
      policies:
        inlinePolicy: iam-policies/permission-set-billing-reviewers-inline-policy.json
      sessionDuration: 600

Two permission sets, groups assigned to the root OU for admin access and to the management account for billing, and a classic IAM break-glass user in the management account. That user deliberately bypasses Identity Center, so an IdP outage cannot lock me out. A metric filter on its usage fires an alarm, so nobody uses it unnoticed.

LZANTC
Configiam-config.yamlntc_identity_center.tf plus sso_users.json and sso_groups.json
AssignmentsGroups to accounts or OUs, written by handDynamic from the account factory map, or static
BreakglassIAM user plus CloudWatch alarmNot configured in my setup
Identity sourceIdP via Control Tower and Identity CenterInternal store, external IdP (SCIM), or Active Directory
Effort for meA few lines of YAMLOne day, two commits

About the NTC break-glass row: the bootstrap user isn't a break-glass user. If you need one, design it deliberately before you delete the bootstrap credentials.

Order matters

What I underestimated most about NTC is that the phases are numbered 0 to 6, but you don't deploy them in that order and walk away. Some features of an early phase need something from a later one:

flowchart TD
  P0["Phase 0: bootstrap"] --> P1["Phase 1: organizations"]
  P1 --> P2["Phase 2: account factory"]
  P2 --> P3["Phase 3: identity center"]
  P2 --> P4["Phase 4: log archive"]
  P4 -.->|"org CloudTrail needs the bucket"| P1
  P4 -.->|"Config baseline needs the bucket"| P2
  P1 -.->|"delegated admins first"| P5["Phase 5: security tooling"]
  P4 --> P5
  P2 --> P6["Phase 6: connectivity"]

CloudTrail in Phase 1 and AWS Config in Phase 2 can only be switched on after the log archive exists, so you go back. Security tooling in Phase 5 needs delegated administrators in Phase 1, so you go back there as well.

My rule of thumb: draw the dependency graph on a whiteboard before you write the first line of HCL, and deploy the log archive right after the account factory.

LZA does not have this problem because one pipeline orders everything through CloudFormation dependencies and the runOrder of your customizations. You pay for it in a different currency: in time per run.

However, NTC's initial setup cost pays back immediately once the setup is done. You will see that later. Update: NTC now also has a version that completes in a single run with one terraform state, similar to the LZA pipeline. So the initial speedup in LZA setup no longer fully counts.

How long does it take?

LZANTC
First thing runningControl Tower 30 to 60 minutesPhase 0 in a few minutes
Feedback per change40 to 75 minutes, any changeA few minutes per phase
Foundation with accounts and SSO1 to 2 daysOrganization on day 1, account factory about two weeks, Identity Center one day
Everything including logging and securitySame pipeline, more configAbout 1 week of calendar time, 15 commits of mine

The NTC calendar time looks long, but most of it was waiting for dependencies and a part-time project, not typing. The effort per phase is small once the previous phase is done.

Who helps you

LZA is open source. You get documentation spread over several AWS sites, GitHub issues that the AWS team answers, and AWS support if you pay for a plan. When I am stuck on a configuration option, the sample configurations are what I open first.

NTC is a commercial product. On Day 1, an engineer from Nuvibit committed fixes straight into my repositories. I will come back to what that is worth in the conclusion, but it set the tone for the whole deployment. I am a Nuvibit partner now, and the NTC landing zone is the foundation of my AWS cloud migration including EU offering.

Conclusion

The getting-started experience shows you what it feels like to live with each platform. LZA gave me a thorough, validated, AWS-native foundation and asked for patience with a slow loop and a Control Tower that has to exist first. NTC gave me a quick bootstrap, a GitOps workflow from the first hour, and an organization that is split into phases I have to order myself.

My rule of thumb for Day 1: if your team lives in CDK and CloudFormation and already runs Control Tower, LZA will feel natural. If your team lives in Terraform and wants fast feedback, NTC will feel natural. Pick the one that matches how your team already works.

Next up is Part 2, where logging and security show how the phases really depend on each other. I hope this helps you plan your own Day 1. See you there.

This post was written with AI assistance and verified plus enhanced by a human.

More from the blog

Keep reading - related notes from recent engagements.

Ready to ship faster on AWS?

Tell us what you are building. We will map the fastest safe path to production and the platform to keep it there.

Notes from production

Occasional, no-fluff writing on AWS, DevOps, and running platforms that stay up. No spam, unsubscribe anytime.

Practical, not promotional
Real lessons from real engagements - architecture, automation, and incident post-mortems.
No spam
A few emails a year at most. Your address is never shared or sold.