Skip to content

Repository files navigation

PollySendGrid

NuGet NuGet Downloads CI License: MIT .NET 10 Ready

Polly v8 resilience for SendGrid — add retry, timeout, and circuit-breaker to any email send in two lines.

var client = new SendGridClient(apiKey);

var resilient = client.WithPolly(pipeline => pipeline
    .AddRetry(new RetryStrategyOptions
    {
        MaxRetryAttempts = 3,
        Delay = TimeSpan.FromSeconds(2),
        BackoffType = DelayBackoffType.Exponential,
        UseJitter = true,
        ShouldHandle = SendGridTransientErrors.IsTransient,
    })
    .AddTimeout(TimeSpan.FromSeconds(30)));

var response = await resilient.SendEmailAsync(msg);

Why PollySendGrid?

SendGrid imposes rate limits and occasionally returns transient errors. Dropped emails mean missed notifications, failed password resets, and lost revenue. This library wraps the response check in Polly v8 so every transient error is retried automatically:

Problem Solution
HTTP 429 rate limit exceeded Auto-thrown as SendGridTransientException and retried
HTTP 500 transient server error Auto-thrown as SendGridTransientException and retried
HTTP 503 service unavailable Auto-thrown as SendGridTransientException and retried
HttpRequestException network failure Caught by SendGridTransientErrors.IsTransient
Cascading failures during an outage Wrap with AddCircuitBreaker

Installation

dotnet add package PollySendGrid
dotnet add package Polly.Core

Quick-start

1. Manual wiring

var client = new SendGridClient(apiKey);

var resilient = client.WithPolly(p => p
    .AddRetry(new RetryStrategyOptions
    {
        MaxRetryAttempts = 3,
        Delay = TimeSpan.FromSeconds(2),
        BackoffType = DelayBackoffType.Exponential,
        UseJitter = true,
        ShouldHandle = SendGridTransientErrors.IsTransient,
    }));

var msg = MailHelper.CreateSingleEmail(from, to, subject, plainText, htmlContent);
var response = await resilient.SendEmailAsync(msg);

2. Dependency injection

builder.Services.AddPollySendGrid(apiKey, pipeline => pipeline
    .AddRetry(new RetryStrategyOptions
    {
        MaxRetryAttempts = 3,
        Delay = TimeSpan.FromSeconds(2),
        BackoffType = DelayBackoffType.Exponential,
        UseJitter = true,
        ShouldHandle = SendGridTransientErrors.IsTransient,
    })
    .AddTimeout(TimeSpan.FromSeconds(30)));

public class EmailService(ResilientSendGridClient client)
{
    public Task<Response> SendAsync(SendGridMessage msg, CancellationToken ct)
        => client.SendEmailAsync(msg, ct);
}

Transient error reference

Condition Why it's transient
SendGridTransientException (HTTP 429) Rate limit — back off and retry
SendGridTransientException (HTTP 500) Transient server error
SendGridTransientException (HTTP 503) Service maintenance or overload
HttpRequestException Network failure

Note: SendGridTransientException is thrown automatically by ResilientSendGridClient when the response status code is in SendGridTransientErrors.StatusCodes. You do not throw it yourself.

API reference

Member Description
ResilientSendGridClient.Inner The underlying ISendGridClient
SendEmailAsync(msg, ct) Sends an email through the pipeline
ExecuteAsync<T>(operation, ct) Runs any ISendGridClient operation through the pipeline
SendGridTransientErrors.IsTransient PredicateBuilder for 429/500/503 + HttpRequestException
SendGridTransientErrors.StatusCodes IReadOnlySet<HttpStatusCode> — TooManyRequests, InternalServerError, ServiceUnavailable
client.WithPolly(pipeline) Wraps ISendGridClient with a pre-built pipeline
client.WithPolly(configure) Builds pipeline inline and wraps the client
services.AddPollySendGrid(configure) DI registration (requires ISendGridClient in DI)
services.AddPollySendGrid(apiKey, configure) DI registration with API key shortcut

Target frameworks

.NET 6 ✅ · .NET 8 ✅ · .NET 9 ✅

Related Packages

Package Downloads Description
PollyHealthChecks Downloads ASP.NET Core health checks for Polly v8 circuit breakers — expose circuit-breaker state (Closed, HalfOpen, Open, Isolated) as /health endpoint responses
PollyBackoff Downloads Backoff delay strategies for Polly v8 resilience pipelines
PollyGrpc Downloads Polly v8 resilience interceptor for gRPC
PollyEFCore Downloads Polly v8 resilience pipelines for Entity Framework Core — wrap every EF Core query and SaveChanges with retry, timeout and circuit-breaker via a single AddPollyResilience() call
PollyRabbitMQ Downloads Polly v8 resilience for RabbitMQ.Client v7+ — retry, circuit-breaker, and timeout for IChannel operations, with built-in RabbitMqTransientErrors predicate covering AlreadyClosedException, BrokerUnreachableException, OperationInterruptedException, and ConnectFailureException
PollyMailKit Downloads Polly v8 resilience pipelines for MailKit — retry, timeout, and circuit-breaker for SmtpClient.SendAsync and any MailKit SMTP operation
PollyMassTransit Downloads Polly v8 resilience pipelines for MassTransit — retry, timeout, and circuit-breaker for IBus.Publish and ISendEndpointProvider.Send
PollyNpgsql Downloads Polly v8 resilience pipelines for Npgsql (PostgreSQL) — retry, timeout, and circuit-breaker for NpgsqlConnection queries and commands, plus a built-in PostgresTransientErrors predicate covering all common PostgreSQL transient SQLSTATE codes
PollyOpenAI Downloads Polly v8 resilience for OpenAI and Azure OpenAI API calls
PollyAzureEventHub Downloads Polly v8 resilience pipelines for Azure Event Hubs — retry, timeout, and circuit-breaker for EventHubProducerClient and EventHubConsumerClient
PollySignalR Downloads Polly v8 reconnect policy for SignalR
PollyElasticsearch Downloads Polly v8 resilience pipelines for Elastic.Clients.Elasticsearch 8+ — retry, timeout, and circuit-breaker for any Elasticsearch operation, plus a built-in ElasticTransientErrors predicate covering rate limiting (429), service unavailability (503), gateway timeouts (504), and connection failures
PollyHangfire Downloads Polly v8 resilience pipelines for Hangfire — retry, timeout, and circuit-breaker for IBackgroundJobClient.Enqueue and Schedule
PollyCosmosDb Downloads Polly v8 resilience pipelines for Azure Cosmos DB — retry, timeout, and circuit-breaker for Container operations, plus a built-in CosmosTransientErrors predicate covering rate limiting (429), timeouts (408), partition failovers (410), and service unavailability (503)
PollyMongo Downloads Polly v8 resilience pipelines for MongoDB.Driver — wrap Find, InsertOne, UpdateOne, DeleteOne and other IMongoCollection calls with retry, timeout, circuit-breaker, and more using a single ResilientMongoCollection decorator
PollyDapper Downloads Polly v8 resilience pipelines for Dapper — wrap QueryAsync, ExecuteAsync, and other Dapper calls with retry, timeout, circuit-breaker, and more using a single ResilientDbConnection decorator
PollyMediatR Downloads Polly v8 resilience pipelines for MediatR — add retry, timeout, circuit-breaker, rate-limiting, hedging, and chaos engineering to any MediatR request handler with a single line of DI registration
PollySqlClient Downloads Polly v8 resilience pipelines for Microsoft.Data.SqlClient (SQL Server and Azure SQL) — retry, timeout, and circuit-breaker for SqlConnection queries and commands, plus a built-in SqlServerTransientErrors predicate covering all common SQL Server and Azure SQL transient error numbers
PollyAzureKeyVault Downloads Polly v8 resilience pipelines for Azure Key Vault — retry, timeout, and circuit-breaker for SecretClient, KeyClient, and CertificateClient
PollyAzureQueueStorage Downloads Polly v8 resilience pipelines for Azure Queue Storage — retry, timeout, and circuit-breaker for Azure.Storage.Queues QueueClient
PollyRedis Downloads Polly v8 resilience for StackExchange.Redis
PollyAzureServiceBus Downloads Polly v8 resilience for Azure Service Bus — retry, circuit breaker, and timeout for sending and receiving messages
PollyAzureBlob Downloads Polly v8 resilience pipelines for Azure Blob Storage — wrap BlobClient and BlobContainerClient operations with retry, timeout, circuit-breaker, and more using ResilientBlobClient and ResilientBlobContainerClient decorators
PollyKafka Downloads Polly v8 resilience for Confluent.Kafka — retry, circuit breaker, and timeout for producers and consumers
PollyAzureTableStorage Downloads Polly v8 resilience pipelines for Azure Table Storage — retry, timeout, and circuit-breaker for Azure.Data.Tables TableClient

💼 Need .NET consulting?

The author of this package is available for consulting on Polly v8 resilience, Azure cloud architecture, and clean .NET design.

→ solidqualitysolutions.com · LinkedIn

License

MIT © Justin Bannister

About

Polly v8 resilience for SendGrid — retry, timeout, circuit-breaker with built-in 429/500/503 transient error detection

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages