diff --git a/src/rm.DelegatingHandlers/DelegateAfterNRequestsHandler.cs b/src/rm.DelegatingHandlers/DelegateAfterNRequestsHandler.cs
new file mode 100644
index 0000000..4ce608b
--- /dev/null
+++ b/src/rm.DelegatingHandlers/DelegateAfterNRequestsHandler.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace rm.DelegatingHandlers;
+
+///
+/// Runs delegates after N requests.
+///
+public class DelegateAfterNRequestsHandler : DelegatingHandler
+{
+ private readonly IDelegateAfterNRequestsHandlerSettings delegateAfterNRequestsHandlerSettings;
+
+ private long n;
+
+ ///
+ public DelegateAfterNRequestsHandler(
+ IDelegateAfterNRequestsHandlerSettings delegateAfterNRequestsHandlerSettings)
+ {
+ this.delegateAfterNRequestsHandlerSettings = delegateAfterNRequestsHandlerSettings
+ ?? throw new ArgumentNullException(nameof(delegateAfterNRequestsHandlerSettings));
+ }
+
+ protected override async Task SendAsync(
+ HttpRequestMessage request,
+ CancellationToken cancellationToken)
+ {
+ if (Interlocked.Read(ref n) >= delegateAfterNRequestsHandlerSettings.N)
+ {
+ await delegateAfterNRequestsHandlerSettings.PreDelegate(request)
+ .ConfigureAwait(false);
+ }
+
+ var response = await base.SendAsync(request, cancellationToken)
+ .ConfigureAwait(false);
+
+ if (Interlocked.Read(ref n) < delegateAfterNRequestsHandlerSettings.N)
+ {
+ Interlocked.Increment(ref n);
+ }
+
+ return response;
+ }
+}
+
+public interface IDelegateAfterNRequestsHandlerSettings
+{
+ long N { get; }
+ Func PreDelegate { get; }
+}
+
+public record class DelegateAfterNRequestsHandlerSettings : IDelegateAfterNRequestsHandlerSettings
+{
+ public long N { get; init; }
+ public Func PreDelegate { get; init; }
+}
diff --git a/tests/rm.DelegatingHandlersTest/DelegateAfterNRequestsHandlerTests.cs b/tests/rm.DelegatingHandlersTest/DelegateAfterNRequestsHandlerTests.cs
new file mode 100644
index 0000000..b6322e6
--- /dev/null
+++ b/tests/rm.DelegatingHandlersTest/DelegateAfterNRequestsHandlerTests.cs
@@ -0,0 +1,99 @@
+using System.Net.Http;
+using AutoFixture;
+using AutoFixture.AutoMoq;
+using NUnit.Framework;
+using rm.DelegatingHandlers;
+
+namespace rm.DelegatingHandlersTest;
+
+[TestFixture]
+public class DelegateAfterNRequestsHandlerTests
+{
+ [Test]
+ public async Task Runs_PreDelegate()
+ {
+ var fixture = new Fixture().Customize(new AutoMoqCustomization());
+
+ var n = 5;
+ var preDelegateExecutedCount = 0;
+ var delegateAfterNRequestsHandler = new DelegateAfterNRequestsHandler(
+ new DelegateAfterNRequestsHandlerSettings
+ {
+ N = n,
+ PreDelegate = (request) =>
+ {
+ preDelegateExecutedCount++;
+ return Task.CompletedTask;
+ }
+ });
+
+ using var invoker = HttpMessageInvokerFactory.Create(
+ fixture.Create(), delegateAfterNRequestsHandler);
+
+ for (int i = 0; i < n; i++)
+ {
+ using var _ = await invoker.SendAsync(fixture.Create(), CancellationToken.None);
+ }
+ using var __ = await invoker.SendAsync(fixture.Create(), CancellationToken.None);
+
+ Assert.AreEqual(1, preDelegateExecutedCount);
+ }
+
+ [Test]
+ public async Task Runs_PreDelegate_After()
+ {
+ var fixture = new Fixture().Customize(new AutoMoqCustomization());
+
+ var n = 5;
+ var preDelegateExecutedCount = 0;
+ var delegateAfterNRequestsHandler = new DelegateAfterNRequestsHandler(
+ new DelegateAfterNRequestsHandlerSettings
+ {
+ N = n,
+ PreDelegate = (request) =>
+ {
+ preDelegateExecutedCount++;
+ return Task.CompletedTask;
+ }
+ });
+
+ using var invoker = HttpMessageInvokerFactory.Create(
+ fixture.Create(), delegateAfterNRequestsHandler);
+
+ for (int i = 0; i < n + 1; i++)
+ {
+ using var _ = await invoker.SendAsync(fixture.Create(), CancellationToken.None);
+ }
+ using var __ = await invoker.SendAsync(fixture.Create(), CancellationToken.None);
+
+ Assert.AreEqual(2, preDelegateExecutedCount);
+ }
+
+ [Test]
+ public async Task Does_Not_Run_PreDelegate()
+ {
+ var fixture = new Fixture().Customize(new AutoMoqCustomization());
+
+ var n = 5;
+ var preDelegateExecutedCount = 0;
+ var delegateAfterNRequestsHandler = new DelegateAfterNRequestsHandler(
+ new DelegateAfterNRequestsHandlerSettings
+ {
+ N = n,
+ PreDelegate = (request) =>
+ {
+ preDelegateExecutedCount++;
+ return Task.CompletedTask;
+ }
+ });
+
+ using var invoker = HttpMessageInvokerFactory.Create(
+ fixture.Create(), delegateAfterNRequestsHandler);
+
+ for (int i = 0; i < n; i++)
+ {
+ using var _ = await invoker.SendAsync(fixture.Create(), CancellationToken.None);
+ }
+ Assert.AreEqual(0, preDelegateExecutedCount);
+ }
+}