SQL Server
Use Nimbus with SQL Server as a message transport — no additional broker required
The Nimbus SQL Server transport stores messages in database tables and delivers them via polling. If your application already uses SQL Server, this is the easiest way to add messaging — no extra broker, no new infrastructure to manage, and HA through your existing SQL Server setup.
Messages are dequeued atomically using DELETE ... OUTPUT with UPDLOCK, READPAST hints, so multiple consumers can drain a queue in parallel without duplicates or blocking.
Installation
dotnet add package Nimbus.Transports.SqlServer
Quick Start
using Nimbus;
using Nimbus.Configuration;
using Nimbus.Transports.SqlServer;
var bus = new BusBuilder()
.Configure()
.WithNames("OrderService", Environment.MachineName)
.WithTransport(new SqlServerTransportConfiguration()
.WithConnectionString("Server=localhost;Database=Nimbus;Integrated Security=true;")
.WithAutoCreateSchema())
.WithTypesFrom(typeProvider)
.WithAutofacDefaults(container)
.Build();
await bus.Start();
WithAutoCreateSchema() creates the three required tables (NimbusMessages, NimbusSubscriptions, NimbusDeadLetters) on startup if they don’t exist. It’s idempotent and safe to leave enabled in production. If you prefer to manage the schema yourself, omit it and create the tables manually using the SQL below.
Configuration
Poll Interval
The default poll interval is 1 second. Reduce it for lower latency at the cost of more database queries:
new SqlServerTransportConfiguration()
.WithConnectionString("...")
.WithPollInterval(TimeSpan.FromMilliseconds(250))
| Poll interval | Message latency | DB queries/consumer/min |
|---|---|---|
| 100 ms | ~100 ms | 600 |
| 250 ms | ~250 ms | 240 |
| 1000 ms (default) | ~1 s | 60 |
| 5000 ms | ~5 s | 12 |
Schema
Three tables are required. WithAutoCreateSchema() creates these automatically, or run the SQL manually:
NimbusMessages
CREATE TABLE dbo.NimbusMessages (
MessageId UNIQUEIDENTIFIER NOT NULL PRIMARY KEY,
Destination NVARCHAR(255) NOT NULL,
Body VARBINARY(MAX) NOT NULL,
VisibleAfter DATETIME2 NOT NULL,
ExpiresAt DATETIME2 NULL
);
CREATE INDEX IX_NimbusMessages_Dequeue
ON dbo.NimbusMessages (Destination, VisibleAfter)
INCLUDE (ExpiresAt);
NimbusSubscriptions
CREATE TABLE dbo.NimbusSubscriptions (
TopicName NVARCHAR(255) NOT NULL,
SubscriberQueue NVARCHAR(255) NOT NULL,
PRIMARY KEY (TopicName, SubscriberQueue)
);
NimbusDeadLetters
CREATE TABLE dbo.NimbusDeadLetters (
MessageId UNIQUEIDENTIFIER NOT NULL PRIMARY KEY,
OriginalDestination NVARCHAR(255) NULL,
Body VARBINARY(MAX) NOT NULL,
DeliveryAttempts INT NOT NULL,
FailedAt DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME()
);
Limitations
- Polling-based delivery means latency is bounded by the poll interval
- No large message body store — all payloads stored as
VARBINARY(MAX); use a claim-check pattern for large data
Compatibility
- ✅ SQL Server 2016+
- ✅ Azure SQL Database
- ✅ SQL Server on Linux (Docker)
- ✅ Microsoft.Data.SqlClient 5.x