Create and Configure SQS Queues

The aws:sqs/queue:Queue resource, part of the Pulumi AWS provider, defines an SQS queue: its type (standard or FIFO), message handling behavior, encryption, and failure routing. This guide focuses on three capabilities: standard and FIFO queue configuration, message retention and delivery timing, and dead-letter routing and encryption options.

SQS queues act as message buffers between producers and consumers. They may reference dead-letter queues for failure routing and KMS keys for encryption. The examples are intentionally small. Combine them with your own access policies, Lambda triggers, and monitoring.

Configure a standard queue with message handling

Most deployments start with a standard queue that defines retention, delays, and dead-letter routing for failed messages.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const queue = new aws.sqs.Queue("queue", {
    name: "example-queue",
    delaySeconds: 90,
    maxMessageSize: 2048,
    messageRetentionSeconds: 86400,
    receiveWaitTimeSeconds: 10,
    redrivePolicy: JSON.stringify({
        deadLetterTargetArn: queueDeadletter.arn,
        maxReceiveCount: 4,
    }),
    tags: {
        Environment: "production",
    },
});
import pulumi
import json
import pulumi_aws as aws

queue = aws.sqs.Queue("queue",
    name="example-queue",
    delay_seconds=90,
    max_message_size=2048,
    message_retention_seconds=86400,
    receive_wait_time_seconds=10,
    redrive_policy=json.dumps({
        "deadLetterTargetArn": queue_deadletter["arn"],
        "maxReceiveCount": 4,
    }),
    tags={
        "Environment": "production",
    })
package main

import (
	"encoding/json"

	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/sqs"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		tmpJSON0, err := json.Marshal(map[string]interface{}{
			"deadLetterTargetArn": queueDeadletter.Arn,
			"maxReceiveCount":     4,
		})
		if err != nil {
			return err
		}
		json0 := string(tmpJSON0)
		_, err = sqs.NewQueue(ctx, "queue", &sqs.QueueArgs{
			Name:                    pulumi.String("example-queue"),
			DelaySeconds:            pulumi.Int(90),
			MaxMessageSize:          pulumi.Int(2048),
			MessageRetentionSeconds: pulumi.Int(86400),
			ReceiveWaitTimeSeconds:  pulumi.Int(10),
			RedrivePolicy:           pulumi.String(json0),
			Tags: pulumi.StringMap{
				"Environment": pulumi.String("production"),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var queue = new Aws.Sqs.Queue("queue", new()
    {
        Name = "example-queue",
        DelaySeconds = 90,
        MaxMessageSize = 2048,
        MessageRetentionSeconds = 86400,
        ReceiveWaitTimeSeconds = 10,
        RedrivePolicy = JsonSerializer.Serialize(new Dictionary<string, object?>
        {
            ["deadLetterTargetArn"] = queueDeadletter.Arn,
            ["maxReceiveCount"] = 4,
        }),
        Tags = 
        {
            { "Environment", "production" },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.sqs.Queue;
import com.pulumi.aws.sqs.QueueArgs;
import static com.pulumi.codegen.internal.Serialization.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var queue = new Queue("queue", QueueArgs.builder()
            .name("example-queue")
            .delaySeconds(90)
            .maxMessageSize(2048)
            .messageRetentionSeconds(86400)
            .receiveWaitTimeSeconds(10)
            .redrivePolicy(serializeJson(
                jsonObject(
                    jsonProperty("deadLetterTargetArn", queueDeadletter.arn()),
                    jsonProperty("maxReceiveCount", 4)
                )))
            .tags(Map.of("Environment", "production"))
            .build());

    }
}
resources:
  queue:
    type: aws:sqs:Queue
    properties:
      name: example-queue
      delaySeconds: 90
      maxMessageSize: 2048
      messageRetentionSeconds: 86400
      receiveWaitTimeSeconds: 10
      redrivePolicy:
        fn::toJSON:
          deadLetterTargetArn: ${queueDeadletter.arn}
          maxReceiveCount: 4
      tags:
        Environment: production

When messages fail processing repeatedly, the redrivePolicy routes them to a dead-letter queue after maxReceiveCount attempts. The delaySeconds property postpones initial delivery, while receiveWaitTimeSeconds enables long polling to reduce empty responses. The messageRetentionSeconds property controls how long SQS keeps unprocessed messages before deletion.

Create a FIFO queue with content-based deduplication

Applications requiring strict ordering and exactly-once processing use FIFO queues, which guarantee messages are processed in arrival order.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const queue = new aws.sqs.Queue("queue", {
    name: "example-queue.fifo",
    fifoQueue: true,
    contentBasedDeduplication: true,
});
import pulumi
import pulumi_aws as aws

queue = aws.sqs.Queue("queue",
    name="example-queue.fifo",
    fifo_queue=True,
    content_based_deduplication=True)
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/sqs"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := sqs.NewQueue(ctx, "queue", &sqs.QueueArgs{
			Name:                      pulumi.String("example-queue.fifo"),
			FifoQueue:                 pulumi.Bool(true),
			ContentBasedDeduplication: pulumi.Bool(true),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var queue = new Aws.Sqs.Queue("queue", new()
    {
        Name = "example-queue.fifo",
        FifoQueue = true,
        ContentBasedDeduplication = true,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.sqs.Queue;
import com.pulumi.aws.sqs.QueueArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var queue = new Queue("queue", QueueArgs.builder()
            .name("example-queue.fifo")
            .fifoQueue(true)
            .contentBasedDeduplication(true)
            .build());

    }
}
resources:
  queue:
    type: aws:sqs:Queue
    properties:
      name: example-queue.fifo
      fifoQueue: true
      contentBasedDeduplication: true

Setting fifoQueue to true creates a FIFO queue, which requires the queue name to end with .fifo. The contentBasedDeduplication property enables automatic duplicate detection based on message body content, eliminating the need to provide explicit deduplication IDs.

Scale FIFO throughput per message group

High-volume FIFO workloads can partition throughput limits by message group rather than applying a single limit to the entire queue.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const queue = new aws.sqs.Queue("queue", {
    name: "pulumi-example-queue.fifo",
    fifoQueue: true,
    deduplicationScope: "messageGroup",
    fifoThroughputLimit: "perMessageGroupId",
});
import pulumi
import pulumi_aws as aws

queue = aws.sqs.Queue("queue",
    name="pulumi-example-queue.fifo",
    fifo_queue=True,
    deduplication_scope="messageGroup",
    fifo_throughput_limit="perMessageGroupId")
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/sqs"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := sqs.NewQueue(ctx, "queue", &sqs.QueueArgs{
			Name:                pulumi.String("pulumi-example-queue.fifo"),
			FifoQueue:           pulumi.Bool(true),
			DeduplicationScope:  pulumi.String("messageGroup"),
			FifoThroughputLimit: pulumi.String("perMessageGroupId"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var queue = new Aws.Sqs.Queue("queue", new()
    {
        Name = "pulumi-example-queue.fifo",
        FifoQueue = true,
        DeduplicationScope = "messageGroup",
        FifoThroughputLimit = "perMessageGroupId",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.sqs.Queue;
import com.pulumi.aws.sqs.QueueArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var queue = new Queue("queue", QueueArgs.builder()
            .name("pulumi-example-queue.fifo")
            .fifoQueue(true)
            .deduplicationScope("messageGroup")
            .fifoThroughputLimit("perMessageGroupId")
            .build());

    }
}
resources:
  queue:
    type: aws:sqs:Queue
    properties:
      name: pulumi-example-queue.fifo
      fifoQueue: true
      deduplicationScope: messageGroup
      fifoThroughputLimit: perMessageGroupId

The deduplicationScope property set to messageGroup and fifoThroughputLimit set to perMessageGroupId allow each message group to have its own throughput quota. This configuration increases total queue throughput when messages are distributed across multiple groups.

Enable encryption with SQS-managed keys

Queues handling sensitive data can enable server-side encryption using keys managed entirely by SQS.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const queue = new aws.sqs.Queue("queue", {
    name: "pulumi-example-queue",
    sqsManagedSseEnabled: true,
});
import pulumi
import pulumi_aws as aws

queue = aws.sqs.Queue("queue",
    name="pulumi-example-queue",
    sqs_managed_sse_enabled=True)
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/sqs"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := sqs.NewQueue(ctx, "queue", &sqs.QueueArgs{
			Name:                 pulumi.String("pulumi-example-queue"),
			SqsManagedSseEnabled: pulumi.Bool(true),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var queue = new Aws.Sqs.Queue("queue", new()
    {
        Name = "pulumi-example-queue",
        SqsManagedSseEnabled = true,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.sqs.Queue;
import com.pulumi.aws.sqs.QueueArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var queue = new Queue("queue", QueueArgs.builder()
            .name("pulumi-example-queue")
            .sqsManagedSseEnabled(true)
            .build());

    }
}
resources:
  queue:
    type: aws:sqs:Queue
    properties:
      name: pulumi-example-queue
      sqsManagedSseEnabled: true

Setting sqsManagedSseEnabled to true encrypts messages at rest using SQS-owned keys. This requires no KMS configuration or key management, making it the simplest encryption option.

Encrypt messages with customer-managed KMS keys

Organizations with strict compliance requirements can use customer-managed KMS keys for encryption, enabling audit trails and key rotation.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const queue = new aws.sqs.Queue("queue", {
    name: "example-queue",
    kmsMasterKeyId: "alias/aws/sqs",
    kmsDataKeyReusePeriodSeconds: 300,
});
import pulumi
import pulumi_aws as aws

queue = aws.sqs.Queue("queue",
    name="example-queue",
    kms_master_key_id="alias/aws/sqs",
    kms_data_key_reuse_period_seconds=300)
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/sqs"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := sqs.NewQueue(ctx, "queue", &sqs.QueueArgs{
			Name:                         pulumi.String("example-queue"),
			KmsMasterKeyId:               pulumi.String("alias/aws/sqs"),
			KmsDataKeyReusePeriodSeconds: pulumi.Int(300),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var queue = new Aws.Sqs.Queue("queue", new()
    {
        Name = "example-queue",
        KmsMasterKeyId = "alias/aws/sqs",
        KmsDataKeyReusePeriodSeconds = 300,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.sqs.Queue;
import com.pulumi.aws.sqs.QueueArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var queue = new Queue("queue", QueueArgs.builder()
            .name("example-queue")
            .kmsMasterKeyId("alias/aws/sqs")
            .kmsDataKeyReusePeriodSeconds(300)
            .build());

    }
}
resources:
  queue:
    type: aws:sqs:Queue
    properties:
      name: example-queue
      kmsMasterKeyId: alias/aws/sqs
      kmsDataKeyReusePeriodSeconds: 300

The kmsMasterKeyId property specifies which KMS key to use for encryption. The kmsDataKeyReusePeriodSeconds property controls how long SQS reuses a data key before requesting a new one from KMS, balancing security with KMS API costs.

Beyond these examples

These snippets focus on specific queue-level features: standard and FIFO queue types, message handling (delays, retention, long polling), and dead-letter routing and encryption. They’re intentionally minimal rather than full messaging systems.

The examples may reference pre-existing infrastructure such as dead-letter queues for failure routing and KMS keys for customer-managed encryption. They focus on configuring the queue rather than provisioning everything around it.

To keep things focused, common queue patterns are omitted, including:

  • Queue access policies (use aws.sqs.QueuePolicy resource)
  • Redrive allow policies (use aws.sqs.RedriveAllowPolicy resource)
  • Visibility timeout tuning (visibilityTimeoutSeconds)
  • Message size limits (maxMessageSize)

These omissions are intentional: the goal is to illustrate how each queue feature is wired, not provide drop-in messaging modules. See the SQS Queue resource reference for all available configuration options.

Let's create and Configure SQS Queues

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Queue Policy & Timeouts
Why am I getting timeout errors when creating a queue with a policy?
AWS hangs indefinitely with a timeout error when creating or updating a queue with an associated aws.sqs.QueuePolicy if the policy doesn’t explicitly include Version = "2012-10-17". Always set this version in your policy document to avoid timeouts.
Why isn't my dead letter queue maxReceiveCount working?
When specifying maxReceiveCount in redrivePolicy, you must use an integer (5), not a string (“5”). Using a string value causes the configuration to fail.
Queue Types & Naming
How do I create a FIFO queue?
Set fifoQueue to true and ensure the queue name ends with the .fifo suffix (e.g., “example-queue.fifo”). FIFO queue names must follow this naming convention.
What's the difference between name and namePrefix?
Use name to specify an exact queue name, or namePrefix to generate a unique name with your specified prefix. These properties conflict; you can only use one.
What properties can't I change after creating a queue?
The name, namePrefix, and fifoQueue properties are immutable. You cannot rename a queue or convert between standard and FIFO types after creation.
Dead Letter Queues
How do I set up a dead letter queue?
Configure redrivePolicy with two properties: deadLetterTargetArn (the ARN of your dead letter queue) and maxReceiveCount (an integer specifying retry attempts before moving to DLQ). For example: redrivePolicy: JSON.stringify({ deadLetterTargetArn: dlq.arn, maxReceiveCount: 4 }).
Message Configuration
What are the message retention limits?
Messages can be retained from 60 seconds (1 minute) to 1,209,600 seconds (14 days). The default retention is 345,600 seconds (4 days).
What's the maximum message size I can send?
Messages can be 1,024 bytes (1 KiB) to 1,048,576 bytes (1024 KiB). The default maximum is 262,144 bytes (256 KiB).
How do I delay message delivery?
Set delaySeconds to delay delivery of all messages in the queue. You can delay from 0 to 900 seconds (15 minutes), with a default of 0 (no delay).
Encryption & Security
What are my encryption options for SQS queues?
You have two options: SSE-SQS (set sqsManagedSseEnabled to true for SQS-owned keys) or SSE-KMS (set kmsMasterKeyId to use a customer-managed key). SSE-KMS also supports kmsDataKeyReusePeriodSeconds (60 to 86,400 seconds, default 300).
Performance & Throughput
How do I enable long polling?
Set receiveWaitTimeSeconds to a value between 1 and 20 seconds. The default is 0, which means short polling (immediate return). Long polling reduces empty responses and costs.
What are the visibility timeout limits?
Visibility timeout can be set from 0 to 43,200 seconds (12 hours). The default is 30 seconds. This controls how long a message is hidden from other consumers after being received.
How do I increase throughput for FIFO queues?
For high-throughput FIFO queues, set deduplicationScope to messageGroup and fifoThroughputLimit to perMessageGroupId. This applies throughput quotas per message group instead of per queue.
What's the difference between deduplicationScope values?
deduplicationScope controls where deduplication occurs: messageGroup (per message group) or queue (entire queue, the default). Use messageGroup for higher throughput in FIFO queues.
How does content-based deduplication work for FIFO queues?
Set contentBasedDeduplication to true to enable automatic deduplication based on message body content. This eliminates the need to provide explicit deduplication IDs for FIFO queues.

Using a different cloud?

Explore messaging guides for other cloud providers: