A single AWS account for everything is fine for a solo developer. For a company like Razorpay with 50 engineers across product, security, data, and infrastructure teams, a single account creates serious problems — a developer accidentally deletes a production resource, the security team cannot audit what each team is doing, costs cannot be tracked per team, and one misconfigured IAM role gives access to everything at once. Multi-account AWS architecture solves all of this. Each team or environment gets its own account. A dedicated security account monitors everything. A dedicated logging account receives all logs, immutably, from every other account. Service Control Policies (SCPs) enforce guardrails at the organisation level — no individual account, no matter how much IAM access a user has inside it, can override them. This is the account structure that Razorpay, Hotstar, Zerodha, and every serious AWS customer runs in production, usually under the name "landing zone." Building it yourself — by hand, with the AWS CLI, understanding every moving part — is one of the most direct ways to demonstrate senior cloud engineering thinking in an interview or portfolio. ```text The account structure you are building: Management Account (billing and organization control only) | +-- OU: Security | +-- Security Account (GuardDuty aggregation, Security Hub) | +-- OU: Logging | +-- Log Archive Account (all CloudTrail logs centralised here) | +-- OU: Workloads +-- OU: Production | +-- Prod Account (live customer-facing services) +-- OU: Non-Production +-- Dev Account (development) +-- Staging Account (staging) ``` > 💡 **Tip:** By the end of this project you will understand why "landing zone" is treated as its own discipline at large companies — it is the foundation every other piece of infrastructure gets built on top of, and getting it wrong is expensive to fix later.
A single-account AWS setup breaks down as a company grows past a handful of engineers. Consider a fintech company like Razorpay processing real payment data: without account-level isolation, a junior developer testing a script in what they believe is a "dev" environment can accidentally touch production payment records, because IAM permissions inside one account are trivially easy to over-grant and hard to audit at scale. Billing is consolidated into one indistinguishable number, so nobody can answer "how much does the data team's infrastructure actually cost us this month." This project solves both the security and the operational visibility problem simultaneously. **True account-level isolation** means a compromised or misconfigured Dev account cannot reach Production, because IAM namespaces do not cross account boundaries — an IAM role granted in one account has zero implicit access to any other account, regardless of how permissive that role is. **Service Control Policies** add an organisation-wide ceiling on permissions that no account administrator, not even one with `AdministratorAccess`, can raise from inside a member account. **Centralised, immutable logging** means every API call across every account lands in a single, tamper-resistant S3 bucket that member-account administrators cannot delete or modify. > 📌 **Remember:** The management account itself is never used to run workloads. Its only job is to create and organise member accounts, apply SCPs, and control billing. This single discipline — keeping the management account empty — is what protects the entire structure, since the management account is exempt from all SCPs and is therefore the single highest-value target in the whole organisation.
### Milestone 1: Understand the Core Concepts Before You Build Before creating a single account, it's worth understanding exactly what problem each piece of AWS Organizations solves — the CLI commands are simple, but using them without understanding the reasoning behind account boundaries leads to landing zones that look right but leak permissions in subtle ways. **Why multiple accounts instead of multiple VPCs.** The most common misconception among engineers new to this pattern is: "we already have separate VPCs per team — that's the same as separate accounts." It is not. VPCs share the same IAM namespace. A misconfigured IAM role attached to a resource in a development VPC can, if its policy is broad enough, reach production S3 buckets or RDS instances sitting in a different VPC of the *same account*, because IAM permissions are evaluated at the account level, not the VPC level. A developer who has `AdministratorAccess` in what they call "the dev VPC" effectively has administrator access everywhere in that account. AWS billing is also consolidated at the account level, so per-team or per-VPC cost visibility requires manual tagging discipline that is easy to skip. Separate AWS accounts provide genuine isolation that VPCs cannot: * IAM namespaces are completely separate — a role created in the Dev account cannot access Prod resources unless a cross-account trust relationship is explicitly created and granted * An account breach contains the blast radius by design — a compromised Dev account has no automatic path to reach Prod, since there is no implicit trust between sibling accounts * Billing and cost allocation become natural rather than a tagging exercise — every account has its own Cost Explorer view, its own budget alerts, and its own invoice line * Security controls enforced at the account boundary are enforced by AWS itself at the API layer — not merely by policies your team writes and could forget to apply consistently **What Service Control Policies actually do.** SCPs are JSON policies attached to an OU or an individual account that define the *maximum* permissions any IAM entity in that account can ever have — they are a ceiling, never a grant. An SCP never gives anyone a permission; it can only take permissions away from what IAM would otherwise allow. A concrete example used later in this project: an SCP that denies all actions outside `ap-south-1` and `ap-southeast-1`. Even a user with a full `AdministratorAccess` IAM policy attached cannot create an EC2 instance in `us-east-1`, because the SCP evaluates before IAM and blocks the action with an explicit deny that no IAM policy in the member account can override. SCPs are attached to OUs (affecting every account under that OU) or directly to individual accounts. The management account itself is always exempt from every SCP in the organisation — another reason it must never run workloads. **Why a separate Logging account matters.** If CloudTrail logs are stored in the same account that generated them, an attacker (or a careless administrator) who gains sufficient access to that account can delete the very logs that would reveal what they did. Shipping logs immediately to a separate account, with a bucket policy that denies deletion even to that account's own administrators, means the audit trail survives a compromise of any single workload account. ### Milestone 2: Create the AWS Organization Log into your management account — the one you will use to control everything, and the only account that will ever be exempt from SCPs. ```bash ## Create the organization with ALL features enabled ## ALL features is required for SCPs — the default "consolidated ## billing only" feature set does not support SCPs at all aws organizations create-organization --feature-set ALL ``` ```json { "Organization": { "Id": "o-ex1a2b3c4d", "Arn": "arn:aws:organizations::555555555555:organization/o-ex1a2b3c4d", "FeatureSet": "ALL", "MasterAccountId": "555555555555", "MasterAccountEmail": "aws-management@yourcompany.com" } } ``` Retrieve the organisation root ID — every OU you create in the next milestone attaches under this root. ```bash aws organizations list-roots \ --query 'Roots[0].Id' \ --output text ``` ```text r-ab12 ``` > 📌 **Remember:** Save this Root ID somewhere durable — every OU creation command in Milestone 3 references it, and you cannot easily discover it again without another `list-roots` call. ### Milestone 3: Create the Organisational Unit Structure An OU is a folder for accounts inside your organisation. SCPs and other policies attach to OUs, and every account inside that OU automatically inherits them — this is what lets you apply one region-restriction policy to five workload accounts at once instead of five separate times. ```bash ROOT_ID="r-ab12" ## Create Security OU — houses the account that aggregates ## GuardDuty and Security Hub findings from every other account SECURITY_OU=$(aws organizations create-organizational-unit \ --parent-id $ROOT_ID \ --name "Security" \ --query 'OrganizationalUnit.Id' \ --output text) echo "Security OU: $SECURITY_OU" ## Create Logging OU — houses the account that receives every ## account's CloudTrail logs, immutably LOGGING_OU=$(aws organizations create-organizational-unit \ --parent-id $ROOT_ID \ --name "Logging" \ --query 'OrganizationalUnit.Id' \ --output text) echo "Logging OU: $LOGGING_OU" ## Create Workloads OU — the parent for everything that actually ## runs application code WORKLOADS_OU=$(aws organizations create-organizational-unit \ --parent-id $ROOT_ID \ --name "Workloads" \ --query 'OrganizationalUnit.Id' \ --output text) ## Create Production and Non-Production OUs nested under Workloads ## Nesting lets you apply stricter SCPs to Production only PROD_OU=$(aws organizations create-organizational-unit \ --parent-id $WORKLOADS_OU \ --name "Production" \ --query 'OrganizationalUnit.Id' \ --output text) NONPROD_OU=$(aws organizations create-organizational-unit \ --parent-id $WORKLOADS_OU \ --name "Non-Production" \ --query 'OrganizationalUnit.Id' \ --output text) echo "Production OU: $PROD_OU" echo "Non-Production OU: $NONPROD_OU" ``` Verify the structure was created correctly: ```bash ## List all top-level OUs directly under root aws organizations list-organizational-units-for-parent \ --parent-id $ROOT_ID \ --query 'OrganizationalUnits[*].{Name:Name,Id:Id}' \ --output table ``` ```text -------------------------------------------- | ListOrganizationalUnitsForParent | +-----------+------------------------------+ | Id | Name | +-----------+------------------------------+ | ou-ab12-abc123 | Security | | ou-ab12-def456 | Logging | | ou-ab12-ghi789 | Workloads | +-----------+------------------------------+ ``` > 🔴 **Common Mistake:** Nesting all OUs flat under root instead of nesting Production and Non-Production under Workloads makes it much harder to apply a shared SCP (like the region restriction in Milestone 5) to "every workload account" in one step. Design the OU tree around which SCPs need to apply to which groups of accounts, not around your org chart. ### Milestone 4: Create Member Accounts Each account you create becomes a genuinely independent AWS account with its own root user, its own resource limits, and its own IAM namespace — completely isolated from the others by default. ```bash ## Create the Log Archive account ## The email must be globally unique across all of AWS — not used ## by any other AWS account anywhere aws organizations create-account \ --email "aws-logs@yourcompany.com" \ --account-name "LogArchive" \ --iam-user-access-to-billing ALLOW ## Create the Security account aws organizations create-account \ --email "aws-security@yourcompany.com" \ --account-name "Security" \ --iam-user-access-to-billing ALLOW ## Create Development and Production accounts aws organizations create-account \ --email "aws-dev@yourcompany.com" \ --account-name "Development" \ --iam-user-access-to-billing ALLOW aws organizations create-account \ --email "aws-prod@yourcompany.com" \ --account-name "Production" \ --iam-user-access-to-billing ALLOW ``` > 📌 **Remember:** Account creation is asynchronous and typically takes 2–5 minutes. Poll `aws organizations list-accounts` and wait for each account's `Status` to show `ACTIVE` before moving on to the next milestone — moving an account that is still `PENDING` into an OU will fail. Move each newly created account out of the root and into its correct OU: ```bash ## List accounts and note their 12-digit account IDs aws organizations list-accounts \ --query 'Accounts[*].{Name:Name,Id:Id,Status:Status}' \ --output table ``` ```text --------------------------------------------------------- | ListAccounts | +------------------+----------------+-------------------+ | Name | Id | Status | +------------------+----------------+-------------------+ | LogArchive | 111111111111 | ACTIVE | | Security | 222222222222 | ACTIVE | | Development | 333333333333 | ACTIVE | | Production | 444444444444 | ACTIVE | +------------------+----------------+-------------------+ ``` ```bash ## Move the LogArchive account into the Logging OU ## Replace the account ID with the actual value from the table above aws organizations move-account \ --account-id 111111111111 \ --source-parent-id $ROOT_ID \ --destination-parent-id $LOGGING_OU ## Move the Security account into the Security OU aws organizations move-account \ --account-id 222222222222 \ --source-parent-id $ROOT_ID \ --destination-parent-id $SECURITY_OU ## Move Development into Non-Production, Production into Production aws organizations move-account \ --account-id 333333333333 \ --source-parent-id $ROOT_ID \ --destination-parent-id $NONPROD_OU aws organizations move-account \ --account-id 444444444444 \ --source-parent-id $ROOT_ID \ --destination-parent-id $PROD_OU ``` > ⚠️ **Security:** Use shared team email aliases (`aws-prod@yourcompany.com`), never a personal email address, when creating accounts. The root email cannot be changed without access to that exact inbox, and an account created with an individual's personal email becomes unrecoverable the moment that person leaves the company. ### Milestone 5: Create Service Control Policies (SCPs) SCPs are the mechanism that turns "we have separate accounts" into "we have separate accounts with enforced guardrails." Each SCP below solves one specific, common real-world failure mode. ```bash ## SCP 1: Deny actions outside approved regions ## Prevents accidental (or malicious) resource creation in ## regions your company doesn't operate in or audit cat > scp-region-restriction.json << 'EOF' { "Version": "2012-10-17", "Statement": [ { "Sid": "DenyActionsOutsideApSouth1", "Effect": "Deny", "NotAction": [ "iam:*", "organizations:*", "route53:*", "budgets:*", "waf:*", "cloudfront:*", "sts:*", "support:*", "trustedadvisor:*" ], "Resource": "*", "Condition": { "StringNotEquals": { "aws:RequestedRegion": ["ap-south-1", "ap-southeast-1"] } } } ] } EOF REGION_SCP=$(aws organizations create-policy \ --name "RestrictToApprovedRegions" \ --description "Deny all non-global services outside ap-south-1 and ap-southeast-1" \ --content file://scp-region-restriction.json \ --type SERVICE_CONTROL_POLICY \ --query 'Policy.PolicySummary.Id' \ --output text) echo "Region SCP: $REGION_SCP" ## SCP 2: Prevent disabling or tampering with CloudTrail ## This is the single most important guardrail in the whole ## landing zone — CloudTrail must never be turned off cat > scp-protect-cloudtrail.json << 'EOF' { "Version": "2012-10-17", "Statement": [ { "Sid": "DenyCloudTrailDisable", "Effect": "Deny", "Action": [ "cloudtrail:DeleteTrail", "cloudtrail:StopLogging", "cloudtrail:UpdateTrail" ], "Resource": "*" } ] } EOF CLOUDTRAIL_SCP=$(aws organizations create-policy \ --name "ProtectCloudTrail" \ --description "Prevent any account from disabling CloudTrail" \ --content file://scp-protect-cloudtrail.json \ --type SERVICE_CONTROL_POLICY \ --query 'Policy.PolicySummary.Id' \ --output text) echo "CloudTrail SCP: $CLOUDTRAIL_SCP" ## SCP 3: Require server-side encryption on every S3 upload ## Applied only to Production — the highest-sensitivity OU cat > scp-require-s3-encryption.json << 'EOF' { "Version": "2012-10-17", "Statement": [ { "Sid": "DenyS3WithoutEncryption", "Effect": "Deny", "Action": "s3:PutObject", "Resource": "*", "Condition": { "StringNotEquals": { "s3:x-amz-server-side-encryption": ["AES256", "aws:kms"] } } } ] } EOF S3_SCP=$(aws organizations create-policy \ --name "RequireS3Encryption" \ --description "Deny S3 PutObject without server-side encryption" \ --content file://scp-require-s3-encryption.json \ --type SERVICE_CONTROL_POLICY \ --query 'Policy.PolicySummary.Id' \ --output text) echo "S3 encryption SCP: $S3_SCP" ``` Attach each SCP to the correct scope — this is the step that actually activates the guardrail: ```bash ## Region restriction applies to every workload account (Dev + Prod) aws organizations attach-policy \ --policy-id $REGION_SCP \ --target-id $WORKLOADS_OU ## CloudTrail protection applies organisation-wide, so attach to Root aws organizations attach-policy \ --policy-id $CLOUDTRAIL_SCP \ --target-id $ROOT_ID ## S3 encryption is required in Production only, not Dev/Staging aws organizations attach-policy \ --policy-id $S3_SCP \ --target-id $PROD_OU ``` > 🔴 **Common Mistake:** Attaching too many SCPs directly to the root OU restricts every account in the organisation at once, with no way to test the impact on a single team first. Always attach a new SCP to a single non-production account or a small test OU first, verify it behaves exactly as intended, and only then expand its scope outward toward root. ### Milestone 6: Centralise CloudTrail Logs The Log Archive account exists for exactly one purpose: receiving CloudTrail logs from every other account in the organisation, in a way that no member account — not even Production's own administrators — can delete or tamper with. ```bash ## Run this command from inside the LogArchive account ## (assume a role into 111111111111 first) MANAGEMENT_ACCOUNT_ID="555555555555" ## Create the log archive bucket aws s3 mb s3://org-cloudtrail-logs-archive-2026 \ --region ap-south-1 ## Apply a bucket policy allowing CloudTrail from every account ## in the organisation to write logs, but nothing else cat > cloudtrail-bucket-policy.json << 'EOF' { "Version": "2012-10-17", "Statement": [ { "Sid": "AWSCloudTrailAclCheck", "Effect": "Allow", "Principal": {"Service": "cloudtrail.amazonaws.com"}, "Action": "s3:GetBucketAcl", "Resource": "arn:aws:s3:::org-cloudtrail-logs-archive-2026" }, { "Sid": "AWSCloudTrailWrite", "Effect": "Allow", "Principal": {"Service": "cloudtrail.amazonaws.com"}, "Action": "s3:PutObject", "Resource": "arn:aws:s3:::org-cloudtrail-logs-archive-2026/AWSLogs/*", "Condition": { "StringEquals": { "s3:x-amz-acl": "bucket-owner-full-control", "aws:SourceOrgID": "o-ex1a2b3c4d" } } } ] } EOF aws s3api put-bucket-policy \ --bucket org-cloudtrail-logs-archive-2026 \ --policy file://cloudtrail-bucket-policy.json ## Enable versioning so even a permitted delete is recoverable aws s3api put-bucket-versioning \ --bucket org-cloudtrail-logs-archive-2026 \ --versioning-configuration Status=Enabled ``` Create the organisation-wide CloudTrail from the **management account** — an organisation trail is the only kind that automatically captures every member account without configuring CloudTrail separately in each one: ```bash ## This single trail captures API activity from every account ## in the organisation, present and future aws cloudtrail create-trail \ --name org-wide-audit-trail \ --s3-bucket-name org-cloudtrail-logs-archive-2026 \ --is-organization-trail \ --is-multi-region-trail \ --enable-log-file-validation \ --region ap-south-1 ## Start logging immediately aws cloudtrail start-logging \ --name org-wide-audit-trail \ --region ap-south-1 ``` > ⚠️ **Security:** `--enable-log-file-validation` creates a cryptographic digest for every log file, letting you later prove a log file was not tampered with after the fact. This is a required control for most compliance frameworks (SOC 2, PCI-DSS) and costs nothing extra to enable. ### Milestone 7: Enable GuardDuty Organisation-Wide Rather than enabling GuardDuty separately in every account, delegate the Security account as GuardDuty's organisation administrator — findings from every account then aggregate automatically into one place. ```bash ## From the management account: delegate the Security account ## as the GuardDuty administrator for the whole organisation aws guardduty enable-organization-admin-account \ --admin-account-id 222222222222 \ --region ap-south-1 ## From the Security account: create the detector that will ## receive aggregated findings from every member account aws guardduty create-detector \ --enable \ --region ap-south-1 ``` ```text { "DetectorId": "abc123def456abc123def456abc12345" } ``` ```bash ## Auto-enable GuardDuty for every account that joins the ## organisation in the future — no manual step needed per account aws guardduty update-organization-configuration \ --detector-id abc123def456abc123def456abc12345 \ --auto-enable \ --region ap-south-1 ``` ### Milestone 8: Automate Guardrail Deployment with CloudFormation StackSets Manually re-running the SCP and CloudTrail setup commands every time a new account joins does not scale. StackSets deploy the same CloudFormation stack across every account in an OU automatically, including accounts created after the StackSet is defined. ```bash cat > baseline-guardrails.yaml << 'EOF' AWSTemplateFormatVersion: '2010-09-09' Description: Baseline security guardrails for every workload account Resources: DefaultVpcFlowLogRole: Type: AWS::IAM::Role Properties: RoleName: flow-logs-role AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: vpc-flow-logs.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: flow-logs-policy PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: '*' AccountPasswordPolicy: Type: AWS::IAM::AccountPasswordPolicy Properties: MinimumPasswordLength: 14 RequireSymbols: true RequireNumbers: true RequireUppercaseCharacters: true RequireLowercaseCharacters: true MaxPasswordAge: 90 PasswordReusePrevention: 5 EOF ## Create the StackSet from the management account aws cloudformation create-stack-set \ --stack-set-name baseline-security-guardrails \ --template-body file://baseline-guardrails.yaml \ --permission-model SERVICE_MANAGED \ --auto-deployment Enabled=true,RetainStacksOnAccountRemoval=false \ --region ap-south-1 ## Deploy it to every account in the Workloads OU, in both ## approved regions, in one command aws cloudformation create-stack-instances \ --stack-set-name baseline-security-guardrails \ --deployment-targets OrganizationalUnitIds=$WORKLOADS_OU \ --regions ap-south-1 ap-southeast-1 \ --region ap-south-1 ``` > 🔴 **Common Mistake:** Using `--permission-model SELF_MANAGED` requires manually creating IAM roles in every target account first, which defeats the purpose of automation. `SERVICE_MANAGED` with `--auto-deployment Enabled=true` lets AWS Organizations handle role creation automatically and — critically — deploys the guardrail stack to any new account added to the OU later, with zero manual steps. ### Milestone 9: Verify the SCPs Actually Work An SCP that looks correct in JSON but was attached to the wrong target, or has a syntax error silently ignored, gives you false confidence. Always verify with a real denied action, not just by reading the policy back. ```bash ## From a workload account (e.g. Development), attempt an action ## in a region the SCP should block aws ec2 describe-instances --region us-east-1 ``` ```text An error occurred (AccessDeniedException) when calling the DescribeInstances operation: User: arn:aws:iam::333333333333:user/developer is not authorized to perform: ec2:DescribeInstances on resource: * with an explicit deny in a service control policy ``` This confirms the SCP is active — even a user with `AdministratorAccess` in the Development account cannot perform EC2 actions in `us-east-1`, because the deny happens before IAM evaluation ever runs.
```bash # 1. Confirm all four member accounts exist and are ACTIVE aws organizations list-accounts \ --query 'Accounts[*].{Name:Name,Status:Status}' \ --output table # 2. Confirm each account sits in the correct OU aws organizations list-accounts-for-parent \ --parent-id $PROD_OU \ --query 'Accounts[*].Name' \ --output text # Expected: Production # 3. Confirm the region-restriction SCP is attached to Workloads aws organizations list-policies-for-target \ --target-id $WORKLOADS_OU \ --filter SERVICE_CONTROL_POLICY \ --query 'Policies[*].Name' \ --output text # Expected: RestrictToApprovedRegions # 4. Confirm CloudTrail is actively logging aws cloudtrail get-trail-status \ --name org-wide-audit-trail \ --region ap-south-1 \ --query 'IsLogging' # Expected: true # 5. Confirm GuardDuty auto-enable is on for new accounts aws guardduty describe-organization-configuration \ --detector-id abc123def456abc123def456abc12345 \ --region ap-south-1 \ --query 'AutoEnable' # Expected: true # 6. Confirm the StackSet deployed successfully to every workload account aws cloudformation list-stack-instances \ --stack-set-name baseline-security-guardrails \ --query 'Summaries[*].{Account:Account,Status:Status}' \ --output table # Expected: every row shows Status CURRENT ```
| Command | What it does | | :--- | :--- | | `aws organizations list-accounts` | List all member accounts and their status | | `aws organizations list-policies` | List all SCPs in the organisation | | `aws organizations list-policies-for-target` | See which SCPs apply to a given OU or account | | `aws organizations describe-policy` | Read the full JSON content of an SCP | | `aws cloudtrail get-trail-status` | Verify the organisation trail is actively logging | | `aws cloudformation list-stack-instances` | Check StackSet deployment status per account |
Using the management account for workloads violates the core principle of multi-account design. The management account should only be used for billing, account vending, and organisation-level control. It can never be restricted by SCPs, which makes it the highest-risk account in the entire organisation. Nothing should ever run in it except the organisation management tooling itself. Attaching too many SCPs directly to the root OU restricts the behaviour of every account simultaneously with no staged rollout. Always test a new SCP against one non-production account or a small test OU first, confirm it behaves exactly as intended, and only then attach it to a broader scope. A misconfigured SCP at the root level affects every account instantly and can lock your own team out of critical services. Creating accounts with personal email addresses makes it impossible to recover the account if the employee who created it leaves the company. Always use shared team email aliases — `aws-prod@yourcompany.com`, never `arjun@yourcompany.com` — since you cannot change an account's root email without access to the exact inbox that received the original verification. Forgetting that SCPs deny both human users and automated roles equally means your own CI/CD pipeline can be blocked by a guardrail meant for people. If an SCP denies `ec2:*` outside approved regions in non-production accounts, a GitHub Actions deployment role running in that account is blocked from touching EC2 in the same way a careless developer would be. Design every SCP with your automation's access patterns in mind, and use `Condition` blocks to carve out exceptions for specific automation roles where genuinely needed. Not enabling CloudTrail specifically on the management account is a critical audit gap that's easy to overlook. Even though the organisation-wide trail covers every member account, the management account is where account creation, SCP changes, and OU restructuring actually happen — and those are exactly the actions you most need an immutable audit trail for.
A single AWS account for everything is fine for a solo developer. For a company like Razorpay with 50 engineers across p...
A single-account AWS setup breaks down as a company grows past a handful of engineers. Consider a fintech company like R...
Milestone 1: Understand the Core Concepts Before You Build Before creating a single account, it's worth understanding ex...
...
Command What it does aws organizations list-accounts List all member accounts and their status aws organizations list-po...
Using the management account for workloads violates the core principle of multi-account design. The management account s...
Aligns directly with DevOps, Site Reliability (SRE), and Platform Engineering job descriptions.