A .NET connector for Amazon Aurora DSQL that wraps Npgsql with automatic IAM authentication. The connector handles token generation, SSL configuration, and connection pooling so you can focus on your application logic.
- Automatic IAM token generation (admin and regular users)
- Connection pooling via
NpgsqlDataSourcewith max lifetime enforcement - Single connection support for simpler use cases
- Flexible host configuration (full endpoint or cluster ID)
- Region auto-detection from endpoint hostname
- Support for AWS profiles and custom credentials providers
- SSL always enabled with
verify-fullmode and direct TLS negotiation - Opt-in OCC retry with exponential backoff and jitter
- Connection string parsing support
- .NET 8.0 or later
- AWS credentials configured (see Credentials Resolution below)
- An Aurora DSQL cluster
For information about creating an Aurora DSQL cluster, see the Getting started with Aurora DSQL guide.
The connector uses the AWS SDK for .NET default credential chain, which resolves credentials in the following order:
- Environment variables (
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY, and optionallyAWS_SESSION_TOKEN) - Shared credentials file (
~/.aws/credentials) with optional profile viaAWS_PROFILEorDsqlConfig.Profile - Shared config file (
~/.aws/config) - IAM role for Amazon EC2/ECS/Lambda (instance metadata or task role)
The first source that provides valid credentials is used. You can override this by specifying Profile for a specific AWS profile or CustomCredentialsProvider for complete control over credential resolution.
dotnet add package Amazon.AuroraDsql.Npgsqlusing Amazon.AuroraDsql.Npgsql;
// Create a connection pool (recommended)
await using var ds = await AuroraDsql.CreateDataSourceAsync(new DsqlConfig
{
Host = "your-cluster.dsql.us-east-1.on.aws"
});
// Read
await using (var conn = await ds.OpenConnectionAsync())
{
await using var cmd = conn.CreateCommand();
cmd.CommandText = "SELECT 'Hello, DSQL!'";
var greeting = await cmd.ExecuteScalarAsync();
Console.WriteLine(greeting);
}
// Transactional write with OCC retry
await ds.WithTransactionRetryAsync(async conn =>
{
await using var cmd = conn.CreateCommand();
cmd.CommandText = "INSERT INTO users (id, name) VALUES (gen_random_uuid(), @name)";
cmd.Parameters.AddWithValue("name", "Alice");
await cmd.ExecuteNonQueryAsync();
});| Property | Type | Default | Description |
|---|---|---|---|
Host |
string |
(required) | Cluster endpoint or 26-char cluster ID |
Region |
string? |
(auto-detected) | AWS region; required if Host is a cluster ID |
User |
string |
"admin" |
Database user |
Database |
string |
"postgres" |
Database name |
Port |
int |
5432 |
Database port |
Profile |
string? |
null |
AWS profile name for credentials |
CustomCredentialsProvider |
AWSCredentials? |
null |
Custom AWS credentials provider |
MaxPoolSize |
int |
10 |
Maximum pool connections |
MinPoolSize |
int |
0 |
Minimum pool connections |
ConnectionLifetime |
int |
3300 (55 min) |
Max connection lifetime in seconds |
ConnectionIdleLifetime |
int |
600 (10 min) |
Max idle time before connection is closed |
OccMaxRetries |
int? |
null (disabled) |
Default max OCC retries for retry methods on the data source |
OrmPrefix |
string? |
null |
ORM prefix prepended to application_name (e.g., "efcore") |
LoggerFactory |
ILoggerFactory? |
null |
Logger factory for retry warnings and diagnostics |
ConfigureConnectionString |
Action<NpgsqlConnectionStringBuilder>? |
null |
Callback to set additional Npgsql connection string properties after defaults |
The connector supports postgres:// and postgresql:// connection string formats:
postgres://[user@]host[:port]/[database][?param=value&...]
postgresql://[user@]host[:port]/[database][?param=value&...]
Supported query parameters:
region- AWS regionprofile- AWS profile name
Examples:
// Full endpoint (region auto-detected)
await using var ds = await AuroraDsql.CreateDataSourceAsync(
"postgres://admin@cluster.dsql.us-east-1.on.aws/postgres");
// With AWS profile
await using var ds = await AuroraDsql.CreateDataSourceAsync(
"postgres://admin@cluster.dsql.us-east-1.on.aws/postgres?profile=dev");For simple scripts or when connection pooling is not needed:
await using var conn = await AuroraDsql.ConnectAsync(new DsqlConfig
{
Host = "your-cluster.dsql.us-east-1.on.aws"
});
await using var cmd = conn.CreateCommand("SELECT * FROM users");
await using var reader = await cmd.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
Console.WriteLine(reader.GetString(0));
}You can also connect from a connection string:
await using var conn = await AuroraDsql.ConnectAsync(
"postgres://admin@cluster.dsql.us-east-1.on.aws/postgres");The DsqlConnection wrapper delegates CreateCommand and exposes the underlying NpgsqlConnection via conn.Connection for advanced use.
Aurora DSQL uses optimistic concurrency control (OCC). When two transactions modify the same data, the first to commit wins and the second receives an OCC error (SQLSTATE 40001).
Use WithTransactionRetryAsync on the data source for transactional writes with automatic OCC retry. It manages BEGIN/COMMIT/ROLLBACK internally and opens a fresh connection for each attempt. Set OccMaxRetries in config for the default, or override per-call:
await using var ds = await AuroraDsql.CreateDataSourceAsync(new DsqlConfig
{
Host = "your-cluster.dsql.us-east-1.on.aws",
OccMaxRetries = 3
});
await ds.WithTransactionRetryAsync(async conn =>
{
await using var cmd = conn.CreateCommand();
cmd.CommandText = "UPDATE accounts SET balance = balance - 100 WHERE id = @from";
cmd.Parameters.AddWithValue("from", fromId);
await cmd.ExecuteNonQueryAsync();
cmd.CommandText = "UPDATE accounts SET balance = balance + 100 WHERE id = @to";
cmd.Parameters.Clear();
cmd.Parameters.AddWithValue("to", toId);
await cmd.ExecuteNonQueryAsync();
});The static OccRetry.WithTransactionRetryAsync overloads are also available for use with a raw NpgsqlDataSource.
For DDL or single DML statements:
await ds.ExecWithRetryAsync("CREATE INDEX ASYNC idx_users_name ON users (name)");The static OccRetry.ExecWithRetryAsync overloads are also available for use with a raw NpgsqlDataSource.
To detect OCC errors in custom retry logic:
try
{
// ... database operations
}
catch (Exception ex) when (OccRetry.IsOccError(ex))
{
// Handle OCC conflict
}The example/ directory contains runnable examples demonstrating various patterns:
| Example | Description |
|---|---|
| ExamplePreferred | Recommended: Connection pool with concurrent queries and transactional write |
| SingleConnection | Single connection without pooling |
| ManualToken | Manual IAM token generation without the connector |
export CLUSTER_ENDPOINT=your-cluster.dsql.us-east-1.on.aws
cd example
dotnet test --filter "ExamplePreferredTest"
dotnet test --filter "SingleConnectionExampleTest"
dotnet test --filter "ManualTokenExampleTest"cd dotnet/npgsql
dotnet build src/Amazon.AuroraDsql.Npgsql/Unit tests (no cluster required):
dotnet test test/unit/Amazon.AuroraDsql.Npgsql.Tests/Integration tests (requires a DSQL cluster):
export CLUSTER_ENDPOINT="your-cluster.dsql.us-east-1.on.aws"
dotnet test test/integration/Amazon.AuroraDsql.Npgsql.IntegrationTests/dotnet format src/Amazon.AuroraDsql.Npgsql/- Amazon Aurora DSQL Documentation
- SQL Feature Compatibility in Aurora DSQL
- Aurora DSQL and PostgreSQL
- Npgsql Documentation
- NpgsqlDataSource API Reference
- AWS SDK for .NET
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0