I assumed GovCloud was AWS with a different region code. It took two weeks to prove me wrong.
I needed a GovCloud account for a multi-tenant NIST compliance platform. I’d been running commercial AWS infrastructure for months — EKS, Terraform, tenant provisioning, the whole stack. GovCloud would be the same thing in a different region. That was the assumption. It lasted about four hours.
The account that doesn’t exist yet
My management account couldn’t call CreateGovCloudAccount. The API returned ConstraintViolationException with a message about not being “enabled for access to GovCloud” and no guidance on what that meant. I filed a support case. AWS enabled the permission two days later, and as a side effect created a standalone GovCloud account that had no relationship to my Organizations structure — an orphan floating in the partition with disconnected root credentials. I still had to find it and deal with it.
When create_gov_cloud_account() finally worked, the response contained two account IDs: a GovCloud workload account and a commercial “linked” account that exists purely for billing. There’s also a third — an AWS-managed account that holds encrypted secrets during the root key retrieval process. Three account IDs for one “account.” I spent an evening confusing them with each other.
The root user who can’t sign in
GovCloud root users have no password. Not “shouldn’t use” — there is no password and no password recovery. Root access is programmatic-only via access keys. To get those keys, I filed a support case from the commercial linked account, provided a KMS key for encryption, and waited for AWS to deliver the credentials via Secrets Manager.
The delivery is one-shot. get-secret-value succeeds once. I had to have a password vault open before running the command, because there was no second chance.
This took five support cases over a week. The first case went to the wrong account. The second used a KMS key in the wrong partition. The third went to the right account with the right key, and AWS rotated the credentials and left them in Secrets Manager encrypted with my KMS key. Five rounds of “close this case and open a new one with the correct details,” each one a day of calendar time.
The partition wall
I assumed I could use my commercial SSO to access GovCloud. I could not. The partitions share nothing — no IAM, no Identity Center, no API endpoints, no role assumption across the boundary. An arn:aws: principal cannot assume an arn:aws-us-gov: role. They are separate AWS environments connected by a billing relationship and nothing else.
I ran aws-whoami against the GovCloud credentials and it crashed: ValueError: not enough values to unpack (expected 2, got 1). The tool parses ARNs by splitting on aws:, expecting two parts. GovCloud returns arn:aws-us-gov:iam::575757575757:root — three parts. Every ARN parser that assumes arn:aws: is a landmine in GovCloud. I filed the issue — aws-cn: has the same problem.
Then I tried setting AWS_DEFAULT_REGION=us-gov-east-1 and AWS_REGION=us-gov-east-1 in my environment. Both exported, both visible in env. The CLI ignored them. sts get-caller-identity without --region returned InvalidClientTokenId — a credentials error that’s actually a region error. The profile config had region = us-gov-east-1 too. Also ignored. Only the explicit --region flag worked.
I think this is deliberate. GovCloud is FedRAMP High. The threat model assumes compromised workstations. Environment variables are trivially exfiltrable — /proc/self/environ, a malicious shell script, a crash dump. Forcing --region means the operator has to be deliberate every time, not relying on ambient state that could be manipulated. Same reason they advise you to delete credentials from ~/.aws/credentials when you’re not actively using them.
The services that aren’t there
S3 Vectors doesn’t exist in GovCloud. The December 2025 GA announcement lists 14 commercial regions and zero GovCloud regions. Lambda code signing arrived in September 2025 — meaning anyone who deployed GovCloud infrastructure before that had to disable a compliance feature in a compliance-focused partition. Graviton4 (M8g) instances landed in us-gov-east-1 in December 2025, five years after Graviton2.
Route53 exists in GovCloud, but you can’t use it for public DNS. Externally-facing services need DNS entries in commercial AWS. Organization-level CloudTrails don’t work either — cloudtrail.amazonaws.com can’t be added as a service principal. Per-account trails only, and new accounts auto-generate trails with random names that you need to delete and replace with your own.
us-gov-west-1 has broader service availability than us-gov-east-1. I picked east. I’m still checking whether everything I need is there.
What I actually learned
GovCloud isn’t commercial AWS with extra paperwork. It’s a different trust model. Every convenience that commercial AWS provides — global STS endpoints, ambient region configuration, persistent credentials on disk, federated identity across accounts, console access for root users — GovCloud deliberately removes because those conveniences are attack surface.
The first GovCloud account took two weeks of calendar time, five support cases, and every assumption I had about AWS identity, region handling, and service availability was wrong. The second account should take hours. Organizations is set up, IAM Identity Center will be running, SSO profiles are a template, and the Terraform provider auth is just another profile. The partition quirks are known and documented now. The ceremony is heavier, but it’s a checklist, not a mystery.
I’m building toward a state where creating the tenth GovCloud tenant is boring. That’s the goal. The first one was anything but.
#aws #govcloud #platform-engineering #multi-tenant #compliance