Table of Contents

AWS SQS Transport

The Amazon SQS transport (BareWire.Transport.AWS.SQS) implements BareWire's ITransportAdapter on top of Amazon Simple Queue Service. It pairs a long-polling consumer with a batched producer (up to 10 messages per SQS batch), tracks in-flight messages with credit-based flow control, and dead-letters via SQS's native RedrivePolicy. FIFO queues, IAM instance-profile auth, and SSE encryption at rest are all supported.

Registration

The ergonomic path is the bundle package BareWire.AWS.SQS, which registers the core engine and the SQS transport in one call via AddBareWireWithSqs. The bus delegate is optional — omit it when transport defaults are enough:

builder.Services.AddBareWireWithSqs(
    transport => transport.Region("eu-central-1"),
    bus =>
    {
        bus.AddConsumer<OrderConsumer>();
        // endpoints, middleware, serializers...
    });

AddBareWireWithSqs is sugar over the explicit two-call form, which remains fully supported (use it when you register more than one transport, or reference the core and transport packages separately):

builder.Services.AddBareWireSqs(transport => transport.Region("eu-central-1"));
builder.Services.AddBareWire(bus => bus.AddConsumer<OrderConsumer>());

Authentication

The transport supports three credential modes through ISqsConfigurator. Prefer the default credential chain or an instance profile in production — both keep secrets out of application configuration. The Secret Access Key is never logged and never appears in diagnostic output.

services.AddBareWireSqs(sqs =>
{
    sqs.Region("eu-central-1");

    // DefaultChain (recommended, default) — IAM role, env vars, shared credentials file:
    sqs.UseDefaultCredentials();

    // IAM instance profile (EC2 instance profile / ECS task role), credentials from IMDS:
    // sqs.UseInstanceProfileCredentials();          // default role attached to the profile
    // sqs.UseInstanceProfileCredentials("MyAppRole"); // or an explicit role name

    // Explicit static credentials (local development only):
    // sqs.UseExplicitCredentials("AKIAIOSFODNN7EXAMPLE", "<secret>");
});

For LocalStack or another SQS-compatible endpoint, point the adapter at a custom URL with ServiceUrl. Plain http is rejected unless you also call AllowInsecureEndpoint() (test environments only):

services.AddBareWireSqs(sqs =>
{
    sqs.ServiceUrl("http://localhost:4566");
    sqs.AllowInsecureEndpoint();  // opt out of TLS enforcement — test only
    sqs.Region("us-east-1");
});

Long-polling consumer

The consumer uses SQS long polling to minimise empty-receive calls. WaitTimeSeconds (0–20, default 20) sets the poll duration, MaxNumberOfMessages (1–10, default 10) the batch size per ReceiveMessage call, VisibilityTimeout (default 30 s) the window before an unsettled message becomes visible again, and MaxInFlightMessages (default 100) bounds the consumed-but-unsettled messages tracked in the in-flight registry. All four are set on ISqsConfigurator (see Configurator options).

Batching

The producer groups outgoing messages into SQS send batches of up to 10, and the consumer retrieves up to 10 messages per ReceiveMessage call. The transport advertises this through its capability flags: NativeDeduplication | DlqNative | BatchReceive.

FIFO queues

FIFO fields are set only when the queue name ends in .fifo; standard queues are unaffected. Declare a FIFO queue (and its DLQ redrive) through QueueDeclaration.Arguments:

new QueueDeclaration("my-orders.fifo", Arguments: new Dictionary<string, object>
{
    ["bw.sqs.fifo"] = true,
    ["bw.sqs.content-based-deduplication"] = true,
    ["bw.sqs.max-receive-count"] = 5,
});

MessageGroupId (the ordering boundary) resolves from the BW-MessageGroupId header, falling back to the auto-stamped correlation-id header — which gives per-saga FIFO ordering with no extra configuration. A FIFO send with no resolvable group id fails fast with BareWireTransportException. MessageGroupId is an ordering boundary only, never an authorization or tenant-isolation boundary.

MessageDeduplicationId resolves in order: an explicit BW-MessageDeduplicationId header; content-based dedup when enabled (the broker hashes the body); otherwise a deterministic id from a SHA-256 hash of (MessageGroupId + body). Call ContentBasedDeduplication() on the configurator so BareWire sends no explicit id (the queue must have ContentBasedDeduplication=true). On consume, FIFO messages are stamped with broker-trusted BW-MessageGroupId and BW-SequenceNumber headers.

Settlement and dead-lettering

BareWire settlement actions map onto SQS operations as follows:

BareWire action SQS operation
Ack DeleteMessage — permanent removal
Nack / Requeue / Defer ChangeMessageVisibility(0) — release for redelivery
Reject No operation — RedrivePolicy moves it to the DLQ once maxReceiveCount is exhausted

SQS has no native dead-letter API, so Reject deliberately does not delete the message — that would silently discard it without triggering the DLQ. Dead-lettering is a RedrivePolicy on the queue, configured via the bw.sqs.max-receive-count argument (default 5).

See: Retry and Dead Letter Queues for the general retry/DLQ model.

Encryption at rest

Server-side encryption is a per-queue, opt-in attribute — a queue without an SSE argument is not encrypted by BareWire. SSE-SQS (bw.sqs.sse-managed) and SSE-KMS (bw.sqs.kms-master-key-id, with optional bw.sqs.kms-data-key-reuse-period) are mutually exclusive; setting both throws at deploy time.

// SSE-KMS with a customer CMK
new QueueDeclaration("payments", Arguments: new Dictionary<string, object>
{
    ["bw.sqs.kms-master-key-id"] = "alias/my-cmk",   // key id or ARN
    ["bw.sqs.kms-data-key-reuse-period"] = 300,       // optional, 60–86400
});

Configurator options

ISqsConfigurator method Default Description
UseDefaultCredentials() (default) AWS SDK default credential chain
UseExplicitCredentials(key, secret) Static Access Key ID + Secret Access Key
UseInstanceProfileCredentials(role?) IAM instance profile (EC2 / ECS task role) via IMDS
Region(string) (env) AWS region name (e.g. eu-central-1)
ServiceUrl(string) (AWS) Custom endpoint URL (LocalStack / SQS-compatible)
AllowInsecureEndpoint() false Opt out of TLS enforcement (test only)
VisibilityTimeout(TimeSpan) 30 s Default message visibility timeout
WaitTimeSeconds(int) 20 Long-poll wait time (0–20)
MaxNumberOfMessages(int) 10 Max messages per ReceiveMessage (1–10)
MaxInFlightMessages(int) 100 Max concurrent in-flight messages
ContentBasedDeduplication() off Skip explicit dedup id (broker hashes body)

See also