AWS Managed vs Customer Managed Policies: Which Should You Use?

Use customer managed policies as your default for production. They let you scope permissions to the exact resources your workload needs, they support versioning, and they are easy to audit. Use AWS managed policies when prototyping or when a pre-built policy matches your requirements exactly. Use inline policies only in rare cases where a strict one-to-one binding matters.

Quick answer

AWS gives you three types of IAM policies: AWS managed, customer managed, and inline. The choice affects how much control you have, how easy your permissions are to audit, and how tightly you can scope access.

AWS managed policies are the fastest way to get started. AWS writes and updates them, and they cover common use cases. The tradeoff is that they are often broader than what your application actually needs. AmazonS3ReadOnlyAccess grants read access to every bucket in the account, not just the one your app uses.

Customer managed policies are the best default for production. You write the JSON, you control the scope, and you version each change. When your Lambda function needs access to one DynamoDB table, you write a policy that names that table and nothing more. This is how you apply the principle of least privilege in practice.

Inline policies are embedded directly into a single IAM entity. They cannot be reused, they do not appear in the central policy list, and they are deleted when the entity is deleted. They are acceptable for temporary debugging or strict one-off bindings, but they are a poor choice for anything you need to maintain or audit.

Tip

If you are unsure which type to pick, start with a customer managed policy. You can always loosen it later. Starting with a broad AWS managed policy and trying to tighten it after production is much harder.

Simple explanation

Think of AWS managed policies as pre-built permission templates. AWS wrote them, AWS maintains them, and you attach them as-is. They work like a set menu at a restaurant: fast and convenient, but you cannot swap out the ingredients.

Customer managed policies are your own recipes. You decide exactly which actions are allowed on which resources. You can reuse the same policy across multiple IAM roles, and when requirements change, you update the policy in one place and every role that uses it gets the new version.

Inline policies are handwritten notes stapled to a single role. If you lose the role, you lose the note. Nobody else can read the note unless they open that specific role and look. They work, but they do not scale and they make auditing painful.

Why this matters

The policy type you choose has real consequences as your AWS environment grows:

  • Auditability. Customer managed and AWS managed policies appear in a central list. Inline policies are invisible unless you inspect each role individually. When a security review asks “what can this role do?”, managed policies make the answer fast. Inline policies make it slow.
  • Reuse. Five Lambda functions that need access to the same S3 bucket should share one customer managed policy, not five identical inline policies. When the bucket name changes, you update one policy instead of five.
  • Blast radius. A broad AWS managed policy like AmazonS3FullAccess gives a compromised credential access to every bucket in the account. A customer managed policy scoped to one bucket limits the damage to that bucket. Choosing the right policy type is part of controlling how far a breach can spread.
  • Maintenance. AWS managed policies auto-update when AWS adds new API actions. This is convenient, but it also means new permissions can appear on your roles without your awareness. Customer managed policies change only when you change them.
  • Permission sprawl. Teams that rely on stacking multiple AWS managed policies end up with roles that have far more access than any single workload needs. Designing customer managed policies forces you to think about what each role actually requires.

These tradeoffs matter most in production environments with multiple teams and applications. In a solo dev account, AWS managed policies are fine. In a shared production account, they are a liability unless they happen to match your requirements exactly.

What is an IAM policy?

An IAM policy is a JSON document containing one or more statements. Each statement says: for these actions, on these resources, the effect is Allow or Deny. When a principal (user, role, or service) makes an API call, AWS evaluates all applicable policies and decides whether to allow or deny the request.

Policies do nothing on their own. They take effect only when attached to a user, group, or role. A policy sitting unattached in your account has no effect on anything. For a detailed walkthrough of the JSON structure, see IAM policy structure.

AWS managed policies

AWS managed policies are pre-built policies that AWS creates, maintains, and updates. They cover common use cases and are identified by an ARN that starts with arn:aws:iam::aws:policy/.

Examples include:

  • AmazonS3ReadOnlyAccess: read-only access to all S3 buckets
  • AmazonEC2FullAccess: full control over EC2 resources
  • AWSLambdaBasicExecutionRole: write logs to CloudWatch, used by Lambda
  • ReadOnlyAccess: read-only access to most services
  • AdministratorAccess: full access to everything (use with extreme caution)

Strengths:

  • Zero setup. Attach one policy and you are done.
  • AWS maintains them and updates them when services add new API actions.
  • Well-documented. AWS publishes the full JSON for each one.
  • Good enough for prototyping and labs where precision is not critical.

Weaknesses:

  • Often too broad. AmazonS3ReadOnlyAccess grants read access to every bucket, not just the one your app needs.
  • Not editable. You cannot change a single action or resource in an AWS managed policy.
  • AWS controls updates, so new permissions can appear on your roles without you reviewing them.
  • Encourages permission sprawl when teams stack multiple broad policies instead of designing precise ones.
Note

AWS managed policies are a reasonable starting point during development. Before production, audit what your application actually uses and replace broad managed policies with least-privilege customer managed policies.

Customer managed policies

Customer managed policies are policies you create and own in your AWS account. They have an ARN that includes your account ID: arn:aws:iam::123456789012:policy/MyPolicyName.

You control everything: the name, the JSON content, versioning, and who it gets attached to. When your application needs access to a specific S3 bucket, you write a policy that grants access to exactly that bucket and nothing else:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowAppBucketObjectAccess",
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:DeleteObject"
      ],
      "Resource": "arn:aws:s3:::my-app-uploads/*"
    },
    {
      "Sid": "AllowAppBucketListing",
      "Effect": "Allow",
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::my-app-uploads"
    }
  ]
}

This policy allows access only to my-app-uploads. Compare that to AmazonS3FullAccess, which gives access to every bucket in the account. For details on each field in this JSON, see IAM policy structure.

Strengths:

  • Precise. Scope permissions to the exact resources your workload needs.
  • Versioned. IAM keeps up to 5 versions, so you can roll back changes.
  • Reusable. Attach the same policy to multiple roles, users, or groups.
  • Auditable. Visible in the central IAM policy list, independent of the entities they are attached to.
  • You control updates. No surprise permission changes from AWS.

Weaknesses:

  • You must maintain them. When a service adds a new API action you need, you update the policy yourself.
  • More initial work. You need to understand which actions and resources your app requires, then write and test the JSON.
Tip

You do not need to write customer managed policies from scratch. Use IAM Access Analyzer to generate a policy based on your role’s actual CloudTrail activity, then trim anything extra. This gets you 80% of the way there in minutes.

Inline policies

Inline policies are embedded directly into a single IAM user, group, or role. They are not standalone. If you delete the role, the inline policy is deleted with it. You cannot attach an inline policy to multiple entities.

# Create an inline policy on a role
aws iam put-role-policy \
  --role-name MyLambdaRole \
  --policy-name InlineDynamoDBPolicy \
  --policy-document file://dynamo-policy.json

When inline policies are acceptable:

  • You need a strict one-to-one binding between a policy and a single role, and you want the policy deleted when the role is deleted.
  • You are writing a temporary policy for debugging an AccessDenied error and plan to remove it shortly.
  • You want to guarantee that the policy is never accidentally shared with another entity.

Why inline policies are usually worse:

  • They do not appear in the central IAM policy list. You must inspect each entity individually to find them.
  • They cannot be reused. If two roles need the same permissions, you write and maintain two separate copies.
  • They do not support versioning. There is no rollback if an update breaks something.
  • They create “permission islands” that are easy to lose track of as your account grows.
Warning

Inline policies are the hardest policy type to audit. In production environments, prefer managed policies for all permissions that may apply to more than one role. Reserve inline policies for genuine one-off cases.

How it works in practice

Understanding how policies interact at runtime helps you choose the right type:

  • Policies only matter when attached. An unattached customer managed policy in your account grants zero access. A policy takes effect only when attached to a user, group, or role.
  • Managed policies can be attached to multiple identities. One customer managed policy can be attached to ten different roles. Changes to the policy propagate to all ten roles immediately.
  • Multiple applicable policies are evaluated together. If a role has three attached policies, AWS evaluates all three when deciding whether to allow an API call. An explicit Deny in any policy overrides Allow in all others.
  • Customer managed policies are easier to update centrally. When your bucket name changes, you update one policy document and every role using it picks up the change. With inline policies, you update each role individually.
  • Inline policies create one-off permission islands. Each inline policy lives on exactly one entity. There is no central view, no shared versioning, and no way to bulk-update them. This makes large-scale permission management fragile.

For environments with multiple accounts, Service Control Policies set the permission ceiling across your AWS Organization. An SCP that blocks a service overrides any IAM policy that tries to allow it, regardless of type.

AWS managed vs customer managed vs inline

FeatureAWS ManagedCustomer ManagedInline
Who maintains itAWSYouYou
EditableNoYesYes
Reusable across entitiesYesYesNo
VersioningYes (AWS manages)Yes (up to 5 versions)No
Visible in central policy listYesYesNo
Survives entity deletionYesYesNo
Blast radiusOften high (broad scope)Low (you control scope)Low (single entity)
Best forPrototyping, labs, exact-match use casesProduction workloads, shared permissionsStrict single-entity binding, temporary debugging
Avoid whenYou need precise resource scopingThe AWS managed policy already matches exactlyMultiple entities need the same permission

When to use each type

Quick lab or prototype

Attach AmazonS3ReadOnlyAccess or AmazonDynamoDBFullAccess and move on. Precision does not matter when you are testing an idea that may not ship. Replace the managed policy before the workload goes to production.

Lambda execution role

Start with AWSLambdaBasicExecutionRole for CloudWatch log access. This AWS managed policy is narrow enough to be a good fit. Add a customer managed policy for any other resources your function uses (a specific DynamoDB table, an S3 bucket, an SQS queue). This is better than attaching a broad managed policy like AmazonDynamoDBFullAccess.

App that only needs one S3 bucket

Write a customer managed policy scoped to that bucket. The JSON is straightforward and the blast radius is minimal. This is exactly the scenario where customer managed policies pay off the most.

Shared team baseline permissions

Create a customer managed policy that grants the read-only access your team needs across a defined set of resources. Attach it to a group or a set of roles. When the team’s needs change, update the one policy.

One-off debugging

An inline policy is acceptable here. Attach temporary permissions to a specific role, reproduce the issue, then remove the inline policy. Because the policy is tied to one entity and is meant to be short-lived, the lack of reuse and versioning does not matter.

Long-term production workload

Customer managed policies, always. Scope each policy to the specific actions and resource ARNs the workload needs. Version your changes. Review the policy during deployments. This is how you operationalize least privilege.

Terraform-managed IAM

Define customer managed policies in your Terraform configuration. This gives you version control, pull request review, and repeatable deployments across environments. See managing IAM with Terraform for a walkthrough.

Tip

A common pattern is to combine policy types on the same role. Use AWSLambdaBasicExecutionRole (AWS managed) for logging, then add a customer managed policy scoped to your specific DynamoDB table or S3 bucket. You get the convenience of a pre-built policy where it fits and the precision of a custom policy where it matters.

CLI commands for managing customer managed policies

# Create a new customer managed policy
aws iam create-policy \
  --policy-name MyS3BucketPolicy \
  --policy-document file://s3-bucket-policy.json

# List all customer managed policies in your account
aws iam list-policies --scope Local

# Attach the policy to a role
aws iam attach-role-policy \
  --role-name MyAppRole \
  --policy-arn arn:aws:iam::123456789012:policy/MyS3BucketPolicy

# Create a new version of an existing policy
aws iam create-policy-version \
  --policy-arn arn:aws:iam::123456789012:policy/MyS3BucketPolicy \
  --policy-document file://updated-policy.json \
  --set-as-default

For a full walkthrough of CLI-based IAM management, see managing IAM with the AWS CLI.

Common mistakes

  1. Using broad AWS managed policies in production. AdministratorAccess and AmazonS3FullAccess are fine for testing, but they give compromised credentials access to far more than any single workload needs. Replace them with customer managed policies scoped to specific resources before going live.
  2. Relying on inline policies for everything. Inline policies are invisible in the IAM policy list and cannot be reused. Teams that default to inline policies end up with duplicate permission sets scattered across dozens of roles, making audits and updates painful.
  3. Copying an AWS managed policy without trimming it. If you copy AmazonS3ReadOnlyAccess into a customer managed policy, take the time to remove buckets and actions your app does not use. An untrimmed copy gives you the maintenance burden of a customer managed policy with the over-permissioning of a managed one.
  4. Stacking multiple managed policies instead of designing one clean policy. Attaching five AWS managed policies to cover different services often grants far more access than needed. A single well-designed customer managed policy that names only the required actions and resources is cleaner and easier to audit.
  5. Failing to review permission scope over time. Applications change. Features get removed. The S3 bucket that was critical six months ago might be decommissioned. Review your customer managed policies periodically using CloudTrail logs and IAM Access Analyzer to identify unused permissions.
  6. Not versioning customer managed policies. IAM supports up to 5 policy versions. When you update a policy, create a new version rather than replacing the current one, so you can roll back if the change breaks something.
  7. Attaching too many policies to one role. A role can have up to 10 managed policies attached. If you are approaching that limit, consolidate permissions into fewer, well-designed customer managed policies rather than continuing to stack narrow ones.

AWS managed vs customer managed: real examples

Prototype app reading from S3

You are testing a new file-processing Lambda. Attach AmazonS3ReadOnlyAccess and iterate quickly. The broad scope does not matter because no production data is involved and the role will be replaced or tightened before launch.

Production app with one bucket and one DynamoDB table

Write a customer managed policy with two statement blocks: one scoped to the specific S3 bucket ARN, one scoped to the specific DynamoDB table ARN. Attach it to the application’s execution role. If the credential is compromised, the attacker can only reach those two resources.

Multi-team environment with shared read access

Create a customer managed policy that grants read-only access to a defined set of shared resources (a reporting bucket, a metrics table). Attach it to a group or a shared role. Each team also gets its own customer managed policy for team-specific resources. This keeps shared and team permissions cleanly separated.

CI/CD pipeline or Terraform-managed infrastructure

Define all IAM policies in Terraform or CloudFormation. Customer managed policies are the only type that makes sense here. You version them in source control, review them in pull requests, and deploy them consistently across environments. AWS managed policies cannot be customized, and inline policies cannot be managed declaratively in most IaC tools. For details on this workflow, see managing IAM with Terraform.

Warning

CI/CD pipeline roles are a common source of over-permissioning. Teams often attach AdministratorAccess to unblock deployments and never revisit. A compromised pipeline with admin access can destroy your entire account. Scope pipeline roles to the specific services the pipeline deploys.

How to move from AWS managed to customer managed policies

Replacing a broad AWS managed policy with a precise customer managed policy is straightforward. Here is a practical migration path:

  1. Identify actual required actions. Check CloudTrail logs or use IAM Access Analyzer to see which API calls the role actually makes. Do not guess. Use data.
  2. Start from the working policy. Open the AWS managed policy JSON in the IAM console or retrieve it via the CLI. This shows you every action the policy grants.
  3. Copy only what is needed. Create a new customer managed policy containing only the actions your workload uses. Remove everything else.
  4. Scope resources tightly. Replace wildcard resources ("Resource": "*") with specific ARNs. If your app reads from one S3 bucket, name that bucket. Add conditions where appropriate.
  5. Test the new policy. Attach the customer managed policy alongside the existing AWS managed policy. Monitor for AccessDenied errors. If none appear after a reasonable testing period, the new policy covers everything the workload needs.
  6. Remove the broad policy. Detach the AWS managed policy from the role. Your workload now runs on the tighter customer managed policy.
# Step 1: See what the role actually did in the last 90 days
# Use IAM Access Analyzer in the console, or:
aws accessanalyzer start-policy-generation \
  --policy-generation-details '{"principalArn": "arn:aws:iam::123456789012:role/MyAppRole"}'

# Step 2: Create your scoped-down policy
aws iam create-policy \
  --policy-name MyAppScopedPolicy \
  --policy-document file://scoped-policy.json

# Step 3: Attach new policy alongside old one for testing
aws iam attach-role-policy \
  --role-name MyAppRole \
  --policy-arn arn:aws:iam::123456789012:policy/MyAppScopedPolicy

# Step 4: After testing, remove the broad managed policy
aws iam detach-role-policy \
  --role-name MyAppRole \
  --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess
Note

This migration is low-risk because you test the new policy before removing the old one. Both policies are active during the overlap period, so no permissions are lost until you explicitly detach the broad policy.

Frequently asked questions

What is the difference between AWS managed and customer managed policies?

AWS managed policies are pre-built by AWS and cover broad use cases like AmazonS3ReadOnlyAccess. Customer managed policies are written by you and scoped to the exact resources your workload needs. Both are standalone policies you can attach to multiple users, groups, or roles, but only customer managed policies let you control the content.

Can I edit an AWS managed policy?

No. AWS managed policies are read-only. If you need to modify one, copy its JSON into a new customer managed policy and edit that copy. You control versioning and content of customer managed policies.

When should I use inline policies?

Use inline policies only when you need a strict one-to-one binding between a policy and a single IAM entity, or for temporary debugging permissions you want automatically deleted when the entity is removed. For everything else, use managed policies for better auditability and reuse.

When should I replace an AWS managed policy with a customer managed one?

Replace an AWS managed policy when your workload moves toward production and the managed policy grants access to more resources or actions than your application actually uses. If AmazonS3ReadOnlyAccess gives access to all buckets but your app only reads from one, write a customer managed policy scoped to that bucket.

Do Service Control Policies replace IAM policies?

No. Service Control Policies set the maximum permissions boundary for an entire AWS account or organizational unit. IAM policies grant permissions within that boundary. An SCP that blocks S3 access overrides any IAM policy that allows it, but you still need IAM policies to grant the actual permissions your workloads use.

Last verified: 30 March 2026 Cloud services change frequently. Verify details against official documentation before making infrastructure decisions.