Brighter and AWS: How to setup and use Brighter with AWS SNS/SQS
In this article, we’ll focus on integrating Brighter with AWS SNS/SQS. Introduction to AWS SNS/SQS AWS SNS (Simple Notification Service) and SQS (Simple Queue Service) form a powerful messaging backbone for distributed systems. SNS enables pub/sub messaging (fan-out to multiple consumers), while SQS provides queue-based message buffering for reliable processing. Combining these services with Brighter —a .NET library for command/query handling and messaging—allows you to build resilient, decoupled systems at scale. This guide walks through configuring Brighter to publish events via SNS and consume them via SQS, with practical code examples and workarounds for current limitations. Requirement .NET 8 or superior A .NET project with these NuGet packages Paramore.Brighter.MessagingGateway.AWSSQS: Enables AWS SNS/SQS integration. Paramore.Brighter.ServiceActivator.Extensions.DependencyInjection: Bridge Brighter with AWS messaging services. Paramore.Brighter.ServiceActivator.Extensions.Hosting: Hosts Brighter as a background service. Serilog.AspNetCore: For structured logging (optional but recommended). Brighter Recap Before continuing about AWS SNS/SQS configuration, let's recap what we already know about Brighter. Request (Command/Event) Define messages using IRequest: public class Greeting() : Event(Guid.NewGuid()) { public string Name { get; set; } = string.Empty; } Commands: Single-recipient operations (e.g., SendEmail). Events: Broadcast notifications (e.g., OrderShipped). Message Mapper Translates between Brighter messages and your app objects: public class GreetingMapper : IAmAMessageMapper { public Message MapToMessage(Greeting request) { var header = new MessageHeader(); header.Id = request.Id; header.TimeStamp = DateTime.UtcNow; header.Topic = "greeting.topic"; // The target topic to be publish header.MessageType = MessageType.MT_EVENT; var body = new MessageBody(JsonSerializer.Serialize(request)); return new Message(header, body); } public Greeting MapToRequest(Message message) { return JsonSerializer.Deserialize(message.Body.Bytes)!; } } Request Handler Processes incoming messages: public class GreetingHandler(ILogger logger) : RequestHandler { public override Greeting Handle(Greeting command) { logger.LogInformation("Hello {Name}", command.Name); return base.Handle(command); } } Configuring Brighter with AWS SNS/SQS Define connection settings: var connection = new AWSMessagingGatewayConnection( FallbackCredentialsFactory.GetCredentials(), // The AWS credentials AWSConfigs.RegionEndpoint, // e.g., RegionEndpoint.USWest2 opt => { // Customize AWS client settings }); SQS Consumer Configuration Subscribe to an SQS queue and map it to an SNS topic: .AddServiceActivator(opt => { opt.Subscriptions = [ new SqsSubscription( new SubscriptionName("greeting-subscription"), // Optional: For logging new ChannelName("greeting-queue"), // SQS queue name new RoutingKey("greeting.topic").ToValidSNSTopicName(), // SNS Topic Name bufferSize: 2 // Number of concurrent messages to process ) ]; opt.ChannelFactory = new ChannelFactory(connection); }) SNS Producer Configuration Publish events to SNS: .UseExternalBus(new SnsProducerRegistryFactory(connection, new [] { new SnsPublication { Topic = new RoutingKey("greeting.topic".ToValidSNSTopicName()), MakeChannels = OnMissingChannel.Create } }).Create()); Known Limitations (Brighter v9) Mandatory SNS Dependency: All messages must route through SNS—even for direct SQS use cases. No FIFO Support: FIFO queues/topics (for ordered processing) are unsupported in v9. LocalStack Compatibility Issues: Custom AWS client configurations (e.g., LocalStack endpoints) may not propagate to all internal Brighter components Good News: Brighter v10 (in development) will resolve these issues Best Practices Validate SNS Topic Name Always use .ToValidSNSTopicName() when specifying SNS topics. This Brighter helper method ensures compliance with AWS naming rules (e.g., alphanumeric characters, hyphens, and periods only). new RoutingKey("greeting.topic".ToValidSNSTopicName()) // Converts to a valid SNS topic name Configure Dead Letter Queues (DLQs) Improve fault tolerance by setting up a DLQ for failed messages. Use the redrivePolicy parameter in SqsSubscription to specify: DLQ Name: The name of the SQS queue to hold failed messages. Max Receive Count: Number of retries before messages are moved to the DLQ. new SqsSubscription( subscriptionName: new Subs

In this article, we’ll focus on integrating Brighter with AWS SNS/SQS.
Introduction to AWS SNS/SQS
AWS SNS (Simple Notification Service) and SQS (Simple Queue Service) form a powerful messaging backbone for distributed systems. SNS enables pub/sub messaging (fan-out to multiple consumers), while SQS provides queue-based message buffering for reliable processing. Combining these services with Brighter —a .NET library for command/query handling and messaging—allows you to build resilient, decoupled systems at scale.
This guide walks through configuring Brighter to publish events via SNS and consume them via SQS, with practical code examples and workarounds for current limitations.
Requirement
- .NET 8 or superior
- A .NET project with these NuGet packages
- Paramore.Brighter.MessagingGateway.AWSSQS: Enables AWS SNS/SQS integration.
- Paramore.Brighter.ServiceActivator.Extensions.DependencyInjection: Bridge Brighter with AWS messaging services.
- Paramore.Brighter.ServiceActivator.Extensions.Hosting: Hosts Brighter as a background service.
- Serilog.AspNetCore: For structured logging (optional but recommended).
Brighter Recap
Before continuing about AWS SNS/SQS configuration, let's recap what we already know about Brighter.
Request (Command/Event)
Define messages using IRequest
:
public class Greeting() : Event(Guid.NewGuid())
{
public string Name { get; set; } = string.Empty;
}
- Commands: Single-recipient operations (e.g.,
SendEmail
). - Events: Broadcast notifications (e.g.,
OrderShipped
).
Message Mapper
Translates between Brighter messages and your app objects:
public class GreetingMapper : IAmAMessageMapper<Greeting>
{
public Message MapToMessage(Greeting request)
{
var header = new MessageHeader();
header.Id = request.Id;
header.TimeStamp = DateTime.UtcNow;
header.Topic = "greeting.topic"; // The target topic to be publish
header.MessageType = MessageType.MT_EVENT;
var body = new MessageBody(JsonSerializer.Serialize(request));
return new Message(header, body);
}
public Greeting MapToRequest(Message message)
{
return JsonSerializer.Deserialize<Greeting>(message.Body.Bytes)!;
}
}
Request Handler
Processes incoming messages:
public class GreetingHandler(ILogger<GreetingHandler> logger) : RequestHandler<Greeting>
{
public override Greeting Handle(Greeting command)
{
logger.LogInformation("Hello {Name}", command.Name);
return base.Handle(command);
}
}
Configuring Brighter with AWS SNS/SQS
Define connection settings:
var connection = new AWSMessagingGatewayConnection(
FallbackCredentialsFactory.GetCredentials(), // The AWS credentials
AWSConfigs.RegionEndpoint, // e.g., RegionEndpoint.USWest2
opt => { // Customize AWS client settings });
SQS Consumer Configuration
Subscribe to an SQS queue and map it to an SNS topic:
.AddServiceActivator(opt =>
{
opt.Subscriptions = [
new SqsSubscription<Greeting>(
new SubscriptionName("greeting-subscription"), // Optional: For logging
new ChannelName("greeting-queue"), // SQS queue name
new RoutingKey("greeting.topic").ToValidSNSTopicName(), // SNS Topic Name
bufferSize: 2 // Number of concurrent messages to process
)
];
opt.ChannelFactory = new ChannelFactory(connection);
})
SNS Producer Configuration
Publish events to SNS:
.UseExternalBus(new SnsProducerRegistryFactory(connection, new []
{
new SnsPublication
{
Topic = new RoutingKey("greeting.topic".ToValidSNSTopicName()),
MakeChannels = OnMissingChannel.Create
}
}).Create());
Known Limitations (Brighter v9)
- Mandatory SNS Dependency: All messages must route through SNS—even for direct SQS use cases.
- No FIFO Support: FIFO queues/topics (for ordered processing) are unsupported in v9.
- LocalStack Compatibility Issues: Custom AWS client configurations (e.g., LocalStack endpoints) may not propagate to all internal Brighter components
Good News: Brighter v10 (in development) will resolve these issues
Best Practices
Validate SNS Topic Name
Always use .ToValidSNSTopicName()
when specifying SNS topics. This Brighter helper method ensures compliance with AWS naming rules (e.g., alphanumeric characters, hyphens, and periods only).
new RoutingKey("greeting.topic".ToValidSNSTopicName()) // Converts to a valid SNS topic name
Configure Dead Letter Queues (DLQs)
Improve fault tolerance by setting up a DLQ for failed messages. Use the redrivePolicy
parameter in SqsSubscription
to specify:
- DLQ Name: The name of the SQS queue to hold failed messages.
- Max Receive Count: Number of retries before messages are moved to the DLQ.
new SqsSubscription<Greeting>(
subscriptionName: new SubscriptionName("greeting-subscription"),
channelName: new ChannelName("greeting-queue"),
routingKey: new RoutingKey("greeting.topic").ToValidSNSTopicName(),
bufferSize: 2,
redrivePolicy: new RedrivePolicy(
deadLetterQueueName: "greeting-dead", // DLQ name
maxReceiveCount: 3 // Retry threshold
)
)
Conclusion
Integrating Brighter with AWS SNS/SQS combines the simplicity of the Brighter library with AWS’s scalable messaging infrastructure. While v9 has limitations, its core features enable:
- Decoupled Architecture: Producers and consumers evolve independently.
- Resilience: SQS buffers messages during traffic spikes.
- Scalability: SNS/SQS auto-scales to handle workloads
Reference
Full code: GitHub Repository