Download Latest Version v13.0.1 source code.tar.gz (722.5 kB)
Email in envelope

Get an email when there's a new version of Foundatio

Home / v13.0.0
Name Modified Size InfoDownloads / Week
Parent folder
README.md 2026-04-25 20.9 kB
v13.0.0 source code.tar.gz 2026-04-25 735.4 kB
v13.0.0 source code.zip 2026-04-25 974.6 kB
Totals: 3 Items   1.7 MB 1

v13.0.0

This is a major release with 368 files changed across the entire Foundatio codebase. Here are the themes that define v13:

  • Reliability & Correctness: Dozens of race conditions, deadlocks, and disposal issues have been hunted down and fixed across queues, messaging, caching, and timers. Cancellation tokens are now properly linked to disposal for clean shutdown, and poison messages are gracefully handled instead of crashing consumers.
  • Consistent Error Handling: Every subsystem now has its own exception type (QueueException, MessageBusException, SerializerException) so consumers get predictable, catchable errors regardless of the underlying provider. These feature-specific exceptions are automatically excluded from resilience policy retries.
  • API Normalization: Cache TTL behavior, serializer validation, and expiration return values have been normalized across all implementations -- no more provider-specific quirks.
  • Null Safety: A comprehensive NRT audit eliminated null! suppressions across the codebase, fixing latent null bugs and adding proper nullable attributes. The API surface now accurately communicates nullability contracts.
  • Modern .NET: Dropped netstandard2.0 in favor of net8.0 + net10.0. Replaced DeepCloner with the actively-maintained FastCloner. ScheduledTimer now uses TimeProvider for testability.
  • Documentation Overhaul: Foundatio now has a dedicated documentation site with comprehensive guides, source code links, and real-world examples for every subsystem.

Documentation Site

Foundatio v13 ships with a brand-new documentation site covering every subsystem with guides, configuration examples, and direct source code links. Key additions:

  • New docs site built with VitePress (061bd763)
  • Source code links added to every subsystem: caching (8f6d37c1), queues (bb9af714), messaging (59cc2f57), locks (10241465), jobs (7df97b13), serialization (8819ba09), storage (bf2eb1b9)
  • Comprehensive hybrid caching documentation with RedisHybridCacheClient examples (2fc124df, 0791b496)
  • Cache stampede protection patterns (a6cfd75c)
  • Delayed message delivery and distributed tracing guide (da2c6162)
  • RabbitMQ delayed delivery and delayed-exchange plugin deprecation notes (#490)
  • Redis read routing and replica support guide (6860a0c1)
  • Redis replication lag risk documentation (98323dbe)
  • Queue names vs. queue IDs explainer (456389ed)
  • Cancellation token behavior clarification (70a63d12)
  • Cache expiration differences across implementations (1853daee)
  • Enhanced XML doc comments across all core interfaces (7fdad859)
  • Updated job samples (3e003a86) and added sample projects + benchmarks to the solution (160dd74f)
  • Added Foundatio.Mediator (github.com) links to README and docs (b8f0eba1)

Breaking Changes

  • Dropped netstandard2.0 target: Foundatio now targets net8.0 and net10.0 only. Consumers on .NET Framework or older runtimes must stay on v12.x. by @niemyjski in 4c6aefed, a1089422
  • Normalized ICacheClient.IncrementAsync TTL behavior: Increment operations now consistently apply the TTL parameter across all implementations. Removed ListRemoveAsync ExpiresIn argument to align with all other Remove methods. by @niemyjski in #434
  • Normalized ICacheClient return values for expiration: GetExpirationAsync returns consistent values across implementations. by @niemyjski in #432
  • Normalized ISerializer argument validation: All serializer implementations now consistently validate arguments and throw ArgumentException / ArgumentNullException. by @niemyjski in #440
  • Added QueueException: Queue operations now throw QueueException for queue-specific errors. Guard added against reusing behavior instances. by @niemyjski in #448
  • MessageBusId and QueueId changed to init-only properties: These properties can no longer be set after construction. by @niemyjski in b73bf128
  • Removed obsolete Set/SetAdd/SetRemove methods from cache extensions: These were renamed to List* in v9.0.0 (Nov 2019) and have been [Obsolete] for 6+ years. by @niemyjski in 150beed5
  • Removed obsolete single-parameter GetFileStreamAsync overload: Deprecated in v10.7.0 (Jan 2024) when StreamMode was added. Use the overload accepting StreamMode and CancellationToken. by @niemyjski in 037baae5
  • Comprehensive NRT (Nullable Reference Types) null-safety audit: Eliminated null! suppressions, fixed latent null bugs, and added nullable attributes across the codebase. Return types and parameters may have changed nullability. by @niemyjski in #484, #498

Added

  • Upgrade to xUnit v3 with Foundatio.Xunit.v3: Test infrastructure upgraded to xUnit v3. New Foundatio.Xunit.v3 package with retry test attributes (RetryFactAttribute, RetryTheoryAttribute) for automatic retry of flaky tests. The existing Foundatio.Xunit package continues to support xUnit v2. by @niemyjski in #431
  • Memory-limited in-memory cache: InMemoryCacheClient now supports MaxMemorySize with per-entry size limits and intelligent eviction when memory budgets are exceeded. by @niemyjski, @copilot in #400
  • Poison message handling for queues and message bus: Deserialization failures in queues and the message bus are now gracefully handled as poison messages instead of crashing consumers. Dead letter logging improved. by @niemyjski in #455
  • SerializerException: New exception type for serialization-specific errors, enabling targeted error handling. by @niemyjski in b314a052
  • MessageBusException: Consistent error handling for messaging operations with improved delayed message delivery. by @niemyjski in #443
  • QueueDeleted event on IQueue<T>: Consumers can now subscribe to queue deletion notifications. by @niemyjski in #447
  • OpenTelemetry error recording: Added Activity.AddException polyfill for recording exceptions in distributed traces across all target frameworks. by @niemyjski in #446
  • Synchronous IResiliencePolicy methods: Added sync overloads (Execute, ExecuteAsync) alongside existing async methods. by @ejsmith in #445
  • Feature-specific exceptions excluded from resilience policy retries: QueueException, MessageBusException, StorageException, SerializerException, and CacheException are no longer retried by resilience policies. by @niemyjski in 318fa1a0
  • GetAllExpirationsAsync and SetAllExpirationsAsync on ICacheClient: Bulk expiration read/write support with improved test coverage. by @niemyjski in #426
  • Option to dispose underlying scoped implementations: Scoped cache/queue/etc. wrappers can now optionally dispose their underlying instances. by @niemyjski in #412
  • Job status description: JobStatus now supports a Description property. by @ejsmith in fdcc1442
  • Enforce 5ms minimum expiration across all cache implementations: Prevents extremely short TTLs that cause race conditions. by @niemyjski in #463
  • net10.0 target framework: Added .NET 10 support alongside .NET 8. by @niemyjski in 4c6aefed, a1089422
  • Delayed message delivery: Message bus now supports delayed/scheduled message publishing. by @niemyjski in #443
  • TestCancellationToken in test harness: Added to TestLoggerBase and TestWithLoggingBase (v2 and v3) for better test cancellation support. by @niemyjski in c37508ef, d24afcb7
  • Scoped cache constructor overload: New ScopedCacheClient constructor that defaults shouldDispose to false to prevent accidental disposal. by @niemyjski in f28463b9

Changed

  • Replaced DeepCloner with FastCloner: Switched deep cloning implementation from DeepCloner to FastCloner (v3.5.3) for better performance and active maintenance. Huge thanks to @lofcz (Matej Stagl) for contributing FastCloner and helping integrate it into Foundatio -- this was a major effort that touched the deep internals of the cloning infrastructure. by @niemyjski, @lofcz in #469, #485
  • HybridCacheClient subscription moved out of constructor: Uses AsyncLazy to avoid sync-over-async in constructors. by @niemyjski in 7050c523
  • Improved HybridCacheClient consistency and invalidation: Fixed consistency issues, optimized invalidation, and improved double comparison logic. by @niemyjski in #433
  • ScheduledTimer uses TimeProvider: Scheduled jobs now use TimeProvider for delays, improving testability. by @niemyjski in 77727cdf
  • Two-phase dispose for MessageBus subscription lifecycle: More reliable shutdown behavior. by @niemyjski in #492
  • Cancellation tokens linked to disposal: MessageBus and Queue now link cancellation tokens to disposal for prompt shutdown. by @niemyjski in c06fcdef
  • Improved disposal logic consistency: Disposal guards, IsDisposed consolidation, and proper CancellationTokenSource disposal across all base classes. by @niemyjski in 49eec83a, be62be11
  • Enhanced MessageOptions: Added XML documentation and support for custom properties. by @niemyjski in 692c644d
  • Refactored DataDictionary: Uses TryGetValue, nullable returns, and switch expressions. by @niemyjski in 2b423514
  • Comprehensive XML documentation: Enhanced docs across ICacheClient, IQueue, IMessageBus, IFileStorage, ILockProvider, and IJob interfaces. by @niemyjski in 7fdad859
  • Lock providers accept TimeProvider and IResiliencePolicyProvider: CacheLockProvider and ThrottlingLockProvider now receive dependencies via constructor injection for improved testability and resilience. by @niemyjski in e3e815c4
  • Improved async timeout handling: Refactored AsyncCountdownEvent to use WaitAsync consistently; QueueTestBase now implements IAsyncDisposable. by @niemyjski in d78f220d
  • Updated dependencies: Microsoft.Extensions packages, BenchmarkDotNet, Aspire, Polly, and others updated to latest versions. by @niemyjski, @ejsmith

Fixed

  • Race condition in InMemoryQueue.AbandonAsync: Fixed flaky RunUntilEmptyAsync caused by abandon race. by @niemyjski in #470
  • InvalidCastException in InMemoryCacheClient.GetAsync<object>(): Fixed crash for non-IConvertible types. by @copilot in #468
  • Race condition in ScheduledTimer: Fixed timing issue in scheduled timer callbacks. by @niemyjski in 65e3116a
  • Race condition in HybridCacheClient invalidation tests: Fixed flaky test caused by invalidation timing. by @niemyjski in 5acce8bc
  • InMemoryQueue retry entry isolation: Each retry attempt now creates a fresh queue entry, preventing state leakage between attempts. by @niemyjski in #454
  • Sync-over-async deadlock in MessageBusBase: Fixed deadlock in CancellationToken.Register callback. by @niemyjski in fdc47d22
  • ThrottlingLockProvider period boundary issues: Hardened spin-wait with String.Equals, iteration cap, and improved diagnostics. by @niemyjski in d619b7e3, bbca0e39
  • IndexOutOfRangeException in FastCloner GenerateProcessSetMethod: Fixed array bounds issue in deep cloning. by @niemyjski in f1992944
  • ArgumentOutOfRangeException in DoMaintenance: Prevented negative timespan in queue maintenance scheduling. by @niemyjski in ee00d141
  • DateTime overflow in cache maintenance: Added SafeAdd extension methods to prevent overflow exceptions when adding to DateTime.MaxValue / DateTime.MinValue. by @niemyjski in 6df04edf
  • Zero or negative expiration in ReplaceIfEqualAsync: Now correctly removes the key instead of setting an invalid TTL. by @niemyjski in ffc8d352
  • Null/empty connection strings in ConnectionStringParser: Now handled gracefully instead of throwing. by @niemyjski in df7c6898
  • FaultInjectingSerializer missing ITextSerializer: Now implements ITextSerializer to prevent unexpected Base64 encoding in tests. by @niemyjski in 87fdf6e3
  • Flaky metrics test: Fixed timer resolution race with DateTime.UtcNow. by @niemyjski in #488
  • Queue metrics when disposed: Returns empty metrics instead of throwing. by @lofcz in 4744fc1b

New Contributors

Huge shoutout to @lofcz (Matej Stagl) for his outstanding contributions to this release! Matej is the author of FastCloner, which replaces DeepCloner as Foundatio's deep cloning engine. He contributed the integration PRs (#469, #485), kept FastCloner in sync with upstream improvements, and fixed a queue metrics edge case -- all while being incredibly responsive and collaborative. Thank you, Matej!

  • @niemyjski
  • @ejsmith
  • @lofcz (Matej Stagl) -- FastCloner author and integration contributor
  • @copilot

Migration Guide

Target Framework Changes

v13 drops netstandard2.0 and targets net8.0;net10.0. If you are on .NET Framework, you must stay on Foundatio v12.x.

Cache API Changes

  • IncrementAsync TTL: The TTL parameter now behaves consistently across all cache implementations. Review any code that relied on implementation-specific TTL behavior during increment operations.
  • ListRemoveAsync: The ExpiresIn parameter has been removed. If you were passing an expiration to ListRemoveAsync, remove that argument.
  • GetExpirationAsync: Return values are now normalized. Test any code that compared expiration values across implementations.
  • Minimum expiration: All cache implementations now enforce a 5ms minimum expiration. Values below 5ms will be clamped.

Serializer Changes

  • All ISerializer implementations now validate arguments consistently. If your code was passing null to serializer methods, you will now get ArgumentNullException.
  • SerializerException is now thrown for serialization-specific failures. Update any catch blocks that were catching general exceptions from serializers.

Queue Changes

  • Queue operations now throw QueueException for queue-specific errors. Update exception handling accordingly.
  • Queue behavior instances (e.g., IQueueBehavior<T>) can no longer be reused across multiple queue instances.
  • Poison messages (deserialization failures) are now routed to dead letters instead of crashing consumers. Review dead letter handling if you rely on immediate failure notification.

Messaging Changes

  • MessageBusException is now thrown for messaging errors. Update exception handling.
  • MessageBusId and QueueId are now init-only. Set them during construction only.

Nullable Reference Types

  • Many APIs have updated nullability annotations. If you have NRT enabled, expect new warnings that reflect the corrected nullability contracts. These are accurate -- the previous annotations were incorrect.

Removed APIs

  • CacheClientExtensions.Set / SetAdd / SetRemove (obsolete overloads) -- These were renamed to ListAdd / ListRemove back in v9.0.0 (November 2019) to avoid confusion between "set" as a verb and "set" as a data structure. The old names have been marked [Obsolete] for over 6 years across 4 major versions. Use the List* equivalents.
  • IFileStorage.GetFileStreamAsync(string path) (single-parameter overload) -- Deprecated in v10.7.0 (January 2024) when write-capable file streams were added in #290, which introduced an overload accepting StreamMode and CancellationToken. The single-parameter version has been [Obsolete] for 2+ years. Use GetFileStreamAsync(path, StreamMode.Read, cancellationToken) instead.

Full Changelog: https://github.com/FoundatioFx/Foundatio/compare/v12.0.0...v13.0.0

Source: README.md, updated 2026-04-25