2.4 Managed vs Inline Policies: When to Use Each
Right, let’s settle the great policy placement debate. You’ve got a policy—a beautiful JSON document that grants some specific superpower (or, more likely, the permission to look at a specific S3 bucket). You need to attach it to an IAM User, Group, or Role. You have two choices: Managed or Inline. This isn’t just a stylistic preference; it’s a fundamental architectural decision that will either make your life easier or haunt you at 2 AM.
Think of it like this: a Managed Policy is a reusable, standalone document. You create it, give it a name, and then you can attach it to any number of IAM identities (Users, Groups, Roles). An Inline Policy is exactly what it sounds like: a policy that’s embedded directly into one specific identity. It’s created as a property of that identity and can’t live anywhere else.
The Case for Managed Policies (You Should Use These 90% of the Time)
Managed policies are your best friends. They are the embodiment of the DRY (Don’t Repeat Yourself) principle. You define a permission set once—like ReadOnlyAccessToFinanceData—and attach it to a whole group of users, a specific role, or even a new user next quarter. The magic happens when you need to update that permission. You change the policy document in one place, and the update automatically applies to every single identity that has it attached. This is a godsend for maintenance and consistency.
# Create a managed policy from a JSON file
aws iam create-policy \
--policy-name MyManagedPolicy \
--policy-document file://MyPolicy.json \
--description "My brilliant, reusable policy"
Then, attaching it to a user is a separate, trivial operation:
aws iam attach-user-policy \
--user-name some-user \
--policy-arn arn:aws:iam::123456789012:policy/MyManagedPolicy
See that policy-arn? That’s its unique identifier. You can version it, you can see which identities it’s attached to in the console, and you can use its ARN everywhere—in CloudFormation, Terraform, you name it. This is the way.
The (Very) Niche Case for Inline Policies
So why do inline policies even exist? Mostly for strict, one-to-one relationships where the policy must be deleted if the identity is deleted. The classic example is a service role for an AWS service. When you create an AWS Lambda function, it often creates a role for that function with an inline policy. Why? Because if you delete the function, you want that role and its very specific permissions to be automatically cleaned up too. There’s no orphaned policy left behind to become a security liability.
You can create one like this:
aws iam put-user-policy \
--user-name some-user \
--policy-name MyInlinePolicy \
--policy-document file://MyOtherPolicy.json
Notice the crucial difference: there’s no --policy-arn. This policy is now a part of the user some-user. Its name, MyInlinePolicy, is only unique within the context of that single user. You cannot attach it to anything else. Ever.
The Gotchas and Why You’ll Regret Inline Policies
Here’s the brutal truth: unless you have that specific auto-cleanup requirement, using inline policies is a terrible long-term strategy. They become a management nightmare.
- No Reusability: Need the same set of permissions on a second user? Hope you like copying and pasting JSON. And then maintaining two, five, or fifty separate copies of what is logically the same policy.
- Nightmare Updates: Found a typo in that inline policy? Or need to add one more permission? You now have to find and update every single identity that uses a copy of that policy manually. This is how security holes happen.
- Visibility Suffers: In the IAM console, it’s easy to get a list of all your managed policies and see what they’re attached to. There is no central list of inline policies. They’re hidden away inside their parent identities, waiting to be forgotten.
AWS’s own documentation will often tell you to use inline policies in their quick-start guides because it’s one less step for them to document. It’s the equivalent of giving you a quick, sugary snack instead of a balanced meal. It gets you running fast, but you’ll crash later. Don’t fall for it. Be disciplined. Create the managed policy.
The Verdict
Your default choice for any custom policy should always be a customer-managed policy. Use inline policies only when you are absolutely certain the policy’s lifecycle is inextricably tied to a single identity and must be deleted with it. For everything else—every user permission, every group assignment, every role-based access pattern—the reusability, versioning, and auditability of managed policies will save you from an administrative hellscape. Trust me, I’ve been there. It smells like stale coffee and regret.