SQS queue policies are surprisingly not about granting permissions to SQS, but about granting permissions from SQS to other AWS services.

Let’s see it in action. Imagine you have an SQS queue named my-processing-queue in us-east-1. You want an EC2 instance to be able to poll messages from it. You could attach an IAM policy to the EC2 instance’s IAM role. But what if you want a Lambda function in a different account to be able to send messages to your queue? That’s where queue policies shine.

Here’s a sample queue policy attached directly to my-processing-queue:

{
  "Version": "2012-10-17",
  "Id": "arn:aws:iam::111122223333:role/MyLambdaRole",
  "Statement": [
    {
      "Sid": "AllowLambdaToSendMessages",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111122223333:role/MyLambdaRole"
      },
      "Action": "sqs:SendMessage",
      "Resource": "arn:aws:sqs:us-east-1:444455556666:my-processing-queue"
    }
  ]
}

This policy grants permission to the MyLambdaRole in account 111122223333 to perform the sqs:SendMessage action on the my-processing-queue in account 444455556666. Notice how the Principal specifies an AWS ARN, and the Resource is the ARN of the SQS queue itself. This is the core of resource-based policies.

The problem this solves is cross-account access and allowing services to interact with SQS without needing to explicitly grant SQS permissions in every IAM role that needs to send or receive. Instead, you define these permissions directly on the SQS queue. It’s a centralized way to manage who can talk to your queue.

Internally, when an AWS service (like Lambda, EC2, or another SQS queue) tries to perform an action on your SQS queue, SQS checks two things:

  1. The IAM policy attached to the identity (user, role) making the request. Does that identity have permission to perform the action on this SQS queue?
  2. The SQS queue policy attached to the resource itself. Does the resource (the SQS queue) explicitly grant permission to the identity making the request?

Both must allow the action for it to succeed. If either denies it, or if neither allows it, the request fails. This "least privilege" model means you can be very precise.

The exact levers you control are the Principal (who is allowed/denied), the Action (what they can do – sqs:SendMessage, sqs:ReceiveMessage, sqs:DeleteMessage, etc.), and the Effect (Allow or Deny). You can also add Condition blocks to make permissions even more granular, for example, only allowing SendMessage if a specific message attribute is present.

A common misconception is that if you grant sqs:SendMessage in an IAM role, you don’t need a queue policy. That’s only true if the sender and receiver are in the same account and the sender is acting as itself (not on behalf of another service that needs specific cross-account access). If you need a service in account A to send to a queue in account B, you must have a queue policy in account B allowing the principal from account A.

You can also use queue policies to deny access. For instance, to prevent a specific IAM role from ever deleting messages from your queue, even if its IAM policy would otherwise allow it:

{
  "Version": "2012-10-17",
  "Id": "DenySpecificRole",
  "Statement": [
    {
      "Sid": "DenyDeleteForSpecificRole",
      "Effect": "Deny",
      "Principal": {
        "AWS": "arn:aws:iam::444455556666:role/AdminRole"
      },
      "Action": "sqs:DeleteMessage",
      "Resource": "arn:aws:sqs:us-east-1:444455556666:my-processing-queue"
    }
  ]
}

The order of evaluation for Allow and Deny is crucial: Deny always wins. If any policy (IAM or resource-based) explicitly denies an action, it’s denied, regardless of other Allow statements.

When you are setting up cross-account access for a service like an EC2 instance to poll a queue, you’ll often find yourself needing to add both an IAM policy to the EC2 instance’s role and a queue policy to the SQS queue. The IAM policy on the EC2 role grants it permission to act as an SQS client, while the queue policy on the SQS queue grants the EC2 instance’s IAM role permission to interact with that specific queue.

Understanding how IAM policies and resource-based policies interact is key to mastering SQS access control.

The next hurdle is understanding how message attributes and message body size limits affect your ability to send and receive messages.

Want structured learning?

Take the full Sqs course →