Introduction
Every serious security incident involving a public cloud eventually raises the same question: whose fault was this? In the vast majority of publicized cloud breaches-misconfigured S3 buckets left publicly readable, overly permissive IAM roles, unencrypted RDS snapshots shared by accident-the cloud provider's infrastructure was never compromised. The failure sat squarely on the customer's side of an invisible but well-documented line. That line is the AWS Shared Responsibility Model, and understanding it precisely is one of the highest-leverage things a software engineer or architect can do before shipping anything to production on AWS.
The model is deceptively simple to state and surprisingly easy to misapply. AWS is responsible for the security of the cloud; the customer is responsible for security in the cloud. That single sentence, lifted almost verbatim from AWS's own documentation, is the foundation of nearly every compliance audit, security review, and incident postmortem involving AWS workloads. But the practical implications-what exactly falls on each side, and how that boundary moves depending on which service you use-require a much deeper look. This article walks through the model's mechanics, shows how it behaves differently across infrastructure, container, and abstracted services, and gives concrete, code-level examples of where engineering teams typically get it wrong.
Context: Why a Shared Model Exists at All
Before cloud computing, an organization running its own data center owned the entire stack: the physical building, the racks, the hypervisor, the operating system, the application, and the data. Security was, in principle, a single accountable domain, even if in practice it was poorly staffed or under-resourced. Moving to a public cloud provider does not eliminate this stack-it redistributes ownership of pieces of it between two parties. AWS did not invent this concept in isolation; it formalized a pattern that every major cloud provider (Azure, Google Cloud) now uses in some form, because the alternative-pretending the provider secures everything-creates a false sense of safety that leads directly to breaches.
The redistribution matters because customers frequently assume that "the cloud" is a fully managed, hands-off environment. This assumption is reinforced by marketing language and by genuinely excellent physical and infrastructure security on AWS's side. AWS operates data centers with rigorous physical access controls, redundant power and networking, and third-party audited compliance programs (SOC 1/2/3, ISO 27001, PCI DSS, FedRAMP, and others, all available through AWS Artifact). None of that, however, prevents a developer from attaching an IAM policy with "Action": "*", "Resource": "*" to a Lambda execution role, or from launching an RDS instance with a security group open to 0.0.0.0/0 on port 5432.
The Shared Responsibility Model exists precisely to make this division explicit and auditable. It is referenced directly in compliance frameworks like PCI DSS and HIPAA, because auditors need to know which controls AWS attests to and which controls the customer must independently prove. Cloud Security Alliance guidance and the NIST Cybersecurity Framework both assume this kind of provider/customer split when assessing cloud risk. For an engineering team, treating the model as a checklist item during a compliance audit-rather than as a design constraint from day one-is one of the most common and costly mistakes in cloud adoption.
Deep Technical Explanation: How the Line Moves by Service Category
The most important nuance in the Shared Responsibility Model-and the part most engineers gloss over-is that the dividing line is not fixed. AWS groups its services into three broad categories, and the customer's share of responsibility shrinks as you move up the abstraction ladder. Understanding which category a service falls into should be one of the first questions asked during architecture design, not an afterthought.
Infrastructure as a Service (IaaS), exemplified by EC2, EBS, and VPC, places the largest responsibility on the customer. AWS manages the physical hosts, the hypervisor, and the facilities, but the customer owns the guest operating system, including patching, firewall configuration (security groups and NACLs), identity and access management for anything running on the instance, and all data encryption decisions. If you launch an EC2 instance and never apply an OS security patch, that vulnerability is entirely your liability, regardless of how secure AWS's underlying Nitro hypervisor is.
Container services, such as RDS, ECS, and EMR, shift more of the operational burden to AWS. With RDS, for example, AWS manages the underlying operating system, database engine patching (for supported engines), and the physical infrastructure, while the customer retains responsibility for network access controls, IAM policies governing who can call the RDS API, data-at-rest encryption configuration, and crucially, the actual content and structure of the data itself. This is often where teams get overconfident-assuming that because AWS "manages" RDS, security is largely handled, when in fact access control and encryption configuration remain squarely the customer's job.
Abstracted services, including S3, DynamoDB, SQS, and Lambda, push the boundary furthest toward AWS. Here, AWS operates the entire service platform, including the operating system and platform layer, and the customer is responsible primarily for data classification, access management, and client-side encryption where applicable. Even here, though, the customer is never absolved entirely: an S3 bucket's default access settings, its bucket policy, and its encryption configuration are all customer-controlled, and misconfiguring any of them has caused some of the most widely reported data exposure incidents in cloud history. Lambda functions still require careful IAM role scoping, since an overly broad execution role can turn a single vulnerable dependency into an account-wide compromise.
The practical takeaway is that "AWS manages more" does not mean "you can configure less carefully." It means the specific surface area you're responsible for narrows and shifts-typically converging on identity, data, and configuration regardless of which service tier you're using. This convergence is why IAM is often described as the single most consequential service in the entire AWS ecosystem from a security standpoint.
Implementation: Practical Examples of Drawing the Line
Talking about the model abstractly is useful, but the responsibility boundary becomes concrete the moment you write infrastructure code or IAM policy. Consider a typical scenario: a team provisions an S3 bucket to store customer-uploaded documents. AWS guarantees the durability and physical security of the storage layer, but every one of the following decisions belongs to the customer, and each has been the root cause of real-world breaches.
A minimal, defensible bucket configuration using the AWS SDK for Python (Boto3) looks like this. Note that block-public-access, encryption, and versioning are all explicit customer actions-none of them are AWS's default behavior to enforce on your behalf beyond the account-level default that was introduced in 2023 for newly created buckets:
import boto3
s3 = boto3.client("s3")
bucket_name = "acme-customer-documents-prod"
# 1. Create the bucket (region must be specified explicitly outside us-east-1)
s3.create_bucket(
Bucket=bucket_name,
CreateBucketConfiguration={"LocationConstraint": "eu-west-1"},
)
# 2. Explicitly block all public access - this is a customer decision, not an AWS default guarantee
s3.put_public_access_block(
Bucket=bucket_name,
PublicAccessBlockConfiguration={
"BlockPublicAcls": True,
"IgnorePublicAcls": True,
"BlockPublicPolicy": True,
"RestrictPublicBuckets": True,
},
)
# 3. Enforce server-side encryption with a customer-managed KMS key
s3.put_bucket_encryption(
Bucket=bucket_name,
ServerSideEncryptionConfiguration={
"Rules": [
{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "aws:kms",
"KMSMasterKeyID": "arn:aws:kms:eu-west-1:123456789012:key/abcd-efgh",
},
"BucketKeyEnabled": True,
}
]
},
)
# 4. Enable versioning so accidental or malicious deletes are recoverable
s3.put_bucket_versioning(
Bucket=bucket_name,
VersioningConfiguration={"Status": "Enabled"},
)
The IAM side is equally instructive. A common failure pattern is granting an application's execution role broad S3 permissions "to save time," rather than scoping the policy to exactly the actions and resources the workload needs. Compare a dangerously broad policy to a properly scoped one, expressed as an AWS CDK construct in TypeScript-a pattern many teams use to keep infrastructure and its security posture version-controlled and reviewable in pull requests:
import * as cdk from "aws-cdk-lib";
import * as iam from "aws-cdk-lib/aws-iam";
import * as s3 from "aws-cdk-lib/aws-s3";
import { Construct } from "constructs";
export class DocumentServiceStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const documentsBucket = new s3.Bucket(this, "DocumentsBucket", {
encryption: s3.BucketEncryption.KMS_MANAGED,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
versioned: true,
enforceSSL: true, // rejects any request not made over TLS
});
const processingRole = new iam.Role(this, "DocumentProcessorRole", {
assumedBy: new iam.ServicePrincipal("lambda.amazonaws.com"),
});
// Scoped to specific actions and a specific prefix, not the whole bucket
documentsBucket.grantReadWrite(processingRole, "incoming/*");
// Explicitly deny anything outside the intended actions,
// rather than relying on the absence of a grant
processingRole.addToPolicy(
new iam.PolicyStatement({
effect: iam.Effect.DENY,
actions: ["s3:DeleteBucket", "s3:PutBucketPolicy"],
resources: [documentsBucket.bucketArn],
})
);
}
}
Neither of these examples touches anything AWS is responsible for. AWS ensures the physical drives are redundant, the API endpoint is available, and the storage service itself has no exploitable vulnerability at the platform layer. Everything shown above-encryption key management, access scoping, transport security enforcement-is the customer's half of the shared model, expressed as code that a security reviewer can actually inspect.
Trade-offs and Common Pitfalls
The most persistent pitfall is what security practitioners sometimes call "responsibility drift"-the gradual, undocumented assumption that because AWS manages more of a given service, the team can pay less attention to it over time. This is especially dangerous with managed services like RDS or OpenSearch, where the operational simplicity AWS provides can be mistaken for security simplicity. A database that AWS patches automatically can still be reachable from the public internet if a security group is misconfigured, and no amount of AWS-side patching will compensate for that customer-side error.
A second, subtler pitfall is misunderstanding how the model applies to third-party software running on AWS infrastructure. If a team runs a self-managed Kubernetes cluster on EC2 with a vulnerable container image, or installs an outdated open-source dependency inside a Lambda deployment package, the resulting compromise is unambiguously a customer responsibility, even though the underlying compute is AWS's. Teams sometimes conflate "we're running on AWS" with "AWS is protecting our software supply chain," and that conflation has enabled real incidents involving compromised dependencies and unpatched AMIs. The Shared Responsibility Model is not a statement about AWS's overall trustworthiness-it is a precise, service-by-service boundary that has to be re-evaluated every time a new service or architecture pattern is introduced.
Best Practices for Engineering Teams
Getting the Shared Responsibility Model right in practice is less about memorizing which party owns which layer and more about building organizational habits that keep the boundary visible. The first habit is treating the AWS Well-Architected Framework's Security Pillar as a living design document rather than a one-time checklist. It explicitly maps common controls-least-privilege IAM, encryption at rest and in transit, logging and monitoring via CloudTrail and GuardDuty-to the customer's side of the model, and revisiting it during architecture reviews catches drift before it becomes an incident.
The second habit is automating the customer-side controls wherever possible, rather than relying on manual configuration during service setup. AWS Config rules, Service Control Policies in AWS Organizations, and tools like AWS Security Hub can continuously check for the exact misconfigurations discussed above-public S3 buckets, overly permissive security groups, unencrypted volumes-and flag them before they reach production. Because the customer owns configuration, and humans are unreliable at consistently applying configuration correctly, the only durable fix is to make secure defaults enforceable through policy rather than optional through convention.
Third, teams should explicitly document, per service, what they believe AWS is responsible for versus what their own team owns, and validate that understanding against AWS's official documentation rather than assumption or hearsay. This is particularly important for less common services-AWS's responsibility boundary for something like Amazon Bedrock or a newly released managed service may differ subtly from long-established services like EC2, and documentation is updated as new services launch.
Finally, incident response planning should explicitly account for which layer a given failure mode falls into. A runbook for "unauthorized data access" should distinguish between a scenario where AWS's control plane was compromised (exceptionally rare, and covered by AWS's own incident response) versus a scenario where a customer-side IAM credential was leaked (comparatively common, and entirely within the customer's remediation authority). Conflating these two response paths wastes critical time during an actual incident.
Analogies and Mental Models
A landlord-tenant analogy captures the model reasonably well: the landlord (AWS) is responsible for the building's structural integrity, the fire suppression systems, and the security of the building's common areas. The tenant (the customer) is responsible for locking their own apartment door, deciding who gets a key, and not leaving valuables in plain sight through an open window. No landlord, however diligent, can protect a tenant who leaves their own door unlocked-and no amount of AWS infrastructure security can protect a customer who attaches an administrator policy to a publicly exposed Lambda function.
A second useful mental model is thinking of the responsibility boundary as a service-specific "waterline." Infrastructure services like EC2 sit with the waterline low-most of the stack is exposed and customer-owned. Abstracted services like Lambda or DynamoDB sit with the waterline high-AWS has submerged most of the operational stack below the surface. But no service ever reaches a waterline of zero customer responsibility; identity, data, and configuration always remain above the surface, visible and owned by the customer, no matter how abstracted the service becomes.
The 80/20 Insight
If a team can only internalize one part of the Shared Responsibility Model deeply, it should be this: the overwhelming majority of customer-side cloud security incidents trace back to just three categories-identity and access management, network exposure configuration, and encryption/data handling. This tracks closely with what the Cloud Security Alliance and multiple industry incident reports have identified as the dominant cloud misconfiguration categories over the past decade. A team that rigorously applies least-privilege IAM policies, defaults every network resource to private with explicit, reviewed exceptions, and enforces encryption at rest and in transit by policy rather than convention, will have addressed the vast majority of realistic risk on the customer side of the model-regardless of which specific AWS services they adopt next.
Key Takeaways
- Treat "security of the cloud" versus "security in the cloud" as a design constraint from the first architecture diagram, not a compliance checkbox added before an audit.
- Identify which service category (infrastructure, container, or abstracted) each component of your architecture falls into, and know explicitly what shifts to AWS and what stays with your team.
- Automate enforcement of customer-side controls-block public access, mandatory encryption, least-privilege IAM-through AWS Config, Service Control Policies, or Security Hub rather than relying on manual discipline.
- Re-verify your understanding of the responsibility boundary against current AWS documentation whenever you adopt a new or recently released service.
- Build incident response runbooks that explicitly separate AWS-side failure modes from customer-side failure modes, since the correct remediation path differs sharply between the two.
Conclusion
The AWS Shared Responsibility Model is not a marketing artifact or a legal disclaimer buried in a services agreement-it is an accurate, technically grounded description of where engineering effort needs to be spent. AWS has, by any reasonable measure, built an extraordinarily secure physical and infrastructure layer, backed by third-party audits and a track record that most individual organizations could never replicate on their own. That fact makes it tempting to treat cloud adoption as a wholesale transfer of security responsibility, and that temptation is precisely what causes the majority of cloud security incidents.
The engineers and teams who get this right are the ones who treat the model as a living map that has to be redrawn for every new service, every new architecture pattern, and every new compliance requirement-not a one-time diagram memorized during onboarding. Identity, network configuration, and data handling remain permanently on the customer's side of the line, no matter how abstracted the underlying service becomes. Internalizing that single fact, and building the automated guardrails to enforce it, is the highest-leverage security investment a cloud engineering team can make.
References
- Amazon Web Services. "Shared Responsibility Model." AWS Documentation. https://aws.amazon.com/compliance/shared-responsibility-model/
- Amazon Web Services. "AWS Well-Architected Framework - Security Pillar." https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/welcome.html
- Amazon Web Services. "AWS Artifact." https://aws.amazon.com/artifact/
- Amazon Web Services. "Blocking Public Access to Your Amazon S3 Storage." AWS S3 Documentation. https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-control-block-public-access.html
- Amazon Web Services. "AWS Config." https://aws.amazon.com/config/
- Amazon Web Services. "AWS Security Hub." https://aws.amazon.com/security-hub/
- Amazon Web Services. "IAM Best Practices." https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html
- Cloud Security Alliance. "Top Threats to Cloud Computing." https://cloudsecurityalliance.org/research/topics/top-threats/
- National Institute of Standards and Technology. "NIST Cybersecurity Framework." https://www.nist.gov/cyberframework
- AWS Cloud Development Kit (CDK) Documentation. https://docs.aws.amazon.com/cdk/v2/guide/home.html
- Boto3 Documentation (AWS SDK for Python). https://boto3.amazonaws.com/v1/documentation/api/latest/index.html