Queue

An encrypted SQS queue with a dead-letter queue always provisioned, so failed messages are kept, not dropped. Wire a Lambda consumer in one step.

Messaging · anvil:aws:Queue

Minimal

The smallest config that deploys.

import { App } from '@anvil-cloud/sdk';
import * as anvil from '@anvil-cloud/sdk';

export default new App({
  run(ctx) {
    const jobs = new anvil.aws.Queue('jobs');
  },
});
import anvil_cloud as anvil

def infra(ctx: anvil.Context):
    jobs = anvil.aws.Queue("jobs")

anvil.App(run=infra)
package main

import (
    "github.com/anvil-cloud/anvil/sdk/go/anvil"
    anvilaws "github.com/anvil-cloud/anvil/sdk/go/anvil/aws"
)

func main() {
    anvil.Run(anvil.AppConfig{
        Run: func(ctx *anvil.Context) error {
            _, err := anvilaws.NewQueue(ctx.PulumiCtx(), "jobs", nil)
            if err != nil {
                return err
            }
            return nil
        },
    })
}

Granting access

Let compute send with grantSendMessage. To process messages, set consumer instead: Anvil creates the trigger and the consume permissions together. grantConsumeMessages is for compute that polls the queue itself.

const jobs = new anvil.aws.Queue('jobs', {
  consumer: { lambda: { arn: worker.arn, lambdaRoleArn: worker.roleArn } },
});

jobs.grantSendMessage(api);
jobs = anvil.aws.Queue("jobs",
    # "lambda_" (trailing underscore) because "lambda" is a Python keyword.
    consumer={"lambda_": {"arn": worker.arn, "lambda_role_arn": worker.role_arn}},
)

jobs.grant_send_message(api)
jobs, err := anvilaws.NewQueue(ctx.PulumiCtx(), "jobs", &anvilaws.QueueArgs{
    Consumer: &anvilaws.QueueConsumerArgsArgs{
        Lambda: &anvilaws.QueueLambdaConsumerArgsArgs{Arn: worker.Arn, LambdaRoleArn: worker.RoleArn},
    },
})
if err != nil {
    return err
}

// Go has no grant methods yet: give the Lambda the same actions with permissions.
api, err := anvilaws.NewLambda(ctx.PulumiCtx(), "api", &anvilaws.LambdaArgs{
    Runtime: anvilaws.LambdaRuntime_Nodejs24_x,
    Handler: pulumi.String("functions/api/index.handler"),
    Permissions: anvilaws.LambdaPermissionArray{
        anvilaws.LambdaPermissionArgs{
            Actions:  pulumi.ToStringArray([]string{"sqs:SendMessage"}),
            Resource: jobs.Arn,
        },
    },
})
if err != nil {
    return err
}

What Anvil creates

  • grantSendMessage adds sqs:SendMessage on this queue only.
  • consumer creates the event source mapping and gives the consumer sqs:ReceiveMessage, sqs:DeleteMessage and sqs:GetQueueAttributes on this queue.
  • grantFullAccess also allows ChangeMessageVisibility and PurgeQueue. Use it only when compute really needs to empty the queue.
  • Each grant is an inline policy on the compute's role, removed when you remove the grant.

Good to know

  • A dead-letter queue always exists. A message that fails 3 times moves there instead of being dropped; set dlq to change the count or reuse your own queue.
  • Messages are encrypted at rest.
  • Standard queues deliver at least once and in no guaranteed order, so consumers must handle repeats. fifo: true gives ordering and deduplication at about 3,000 messages a second.

The Full example tab has a complete program. Every argument and attribute is on the Reference tab.