jet/equinox
64.3
Adequate · 22 September 2026
9.7k
lines of production code
F#
primary language
7
measurements over time
What this system is
Equinox is an F\# event sourcing library that provides a unified interface for persisting and querying domain events across multiple storage backends, including Azure Cosmos DB, Amazon DynamoDB, EventStoreDB, and various SQL databases. It supports core event sourcing patterns such as aggregate state folding, snapshotting, and change feeds, while offering built-in primitives for caching, batching, and retry logic to handle concurrent operations efficiently. The system includes comprehensive observability features via Prometheus metrics and OpenTelemetry tracing, along with tooling for performance testing and store inspection.
How it got here
2017–2018 — Modernization and performance optimization
12 changes.
The project underwent significant modernization by migrating to .NET SDK-style projects, upgrading to .NET 6/10, and removing legacy dependencies like Newtonsoft.Json and EventStore. A major focus was placed on performance and observability, introducing a built-in caching layer with ReadThrough support, OpenTelemetry tracing, and detailed logging metrics. The period also expanded the ecosystem with new sample aggregates, an in-memory store for testing, and enhanced CLI tooling for querying and load testing.
2019–2020 — SQL integration and observability
8 changes.
This period focused on expanding storage capabilities by introducing SqlStreamStore integration with connectors for major SQL databases, alongside architectural documentation. It also enhanced core concurrency primitives, optimized Cosmos DB serialization, and added comprehensive Prometheus metrics and integration testing for improved observability and reliability.
2022–2024 — multi-backend event store expansion
7 changes.
This period focused on expanding the Equinox framework by implementing new event store providers for EventStoreDB, Amazon DynamoDB, and PostgreSQL (MessageDb). The work included adding core persistence logic, Prometheus metrics integration for DynamoDB, and comprehensive integration tests to verify the correctness and monitoring capabilities of these new backends.
Features
Add Prometheus metrics logging for Cosmos Store operations
Introduces a new \LogSink\ implementation in the \Equinox.CosmosStore.Prometheus\ module that publishes operational metrics to Prometheus. This component exposes histograms and summaries for operation and round-trip latencies, as well as charge (RU) consumption, and counters for payload events and bytes. Metrics are annotated with labels for database, container, category, operation type, and outcome, allowing users to monitor performance and usage of the Cosmos DB store via standard Prometheus scraping.
src/Equinox.CosmosStore.Prometheus · high confidence
Add SQL Stream Store connectors for MsSql, MySql, and Postgres
New connector implementations have been added for Microsoft SQL Server, MySQL, and PostgreSQL, enabling users to persist event streams using the SqlStreamStore library. Each connector supports optional schema configuration (for MsSql and Postgres), read/write retry policies, and an auto-create schema option to automatically provision the database structure on connection.
src/Equinox.SqlStreamStore.MsSql, src/Equinox.SqlStreamStore.MySql, src/Equinox.SqlStreamStore.Postgres · high confidence
Added C4 architecture and code diagrams for Equinox stores
Added PlantUML diagrams (context, container, component, and code levels) for the Equinox.CosmosStore, Equinox.EventStoreDb, Equinox.SqlStreamStore, and Equinox.MemoryStore implementations. These diagrams document the system architecture, component interactions, and internal query/transact flows for users integrating these specific storage backends.
diagrams · high confidence
Equinox Tool adds Cosmos query, stats, and load test capabilities
The \eqx\ CLI now includes new subcommands for inspecting and testing event stores. The \eqx query\ command allows users to run Cosmos SQL queries against their store, with options to filter by stream or category, export results to files, and control output formatting. The \eqx stats\ command provides insights into store contents, including counts of events, streams, and items, as well as identifying the oldest and newest documents. Additionally, the \eqx loadtest\ command enables performance testing against various backends (Cosmos, DynamoDB, SQL Server, etc.) with configurable parameters for test type, throughput, and duration.
tools/Equinox.Tool · high confidence
Extract in-memory load test harness into standalone tool
The in-memory load testing capabilities previously embedded in the core library have been extracted into a new standalone tool, Equinox.Tools.TestHarness. This tool provides a complete framework for running parallelized, in-memory load tests, including a session pool manager for efficient resource reuse, an event-driven architecture for tracking test runs and session states, and automatic aggregation of latency statistics (min, max, avg, percentiles) and outcome distributions over configurable time buckets. It also includes HTTP helper utilities for capturing detailed request/response data in error scenarios, allowing users to execute and analyze load tests without external infrastructure dependencies.
tools/Equinox.Tools.TestHarness · high confidence
Initial implementation of EventStoreDB integration
Added the \Equinox.EventStoreDb\ module, providing the first concrete implementation of the event store interface using the EventStoreDB gRPC client. This new component handles event persistence and retrieval, including conditional appends with conflict detection, backward/forward stream reads, and detailed structured logging for metrics such as read/write counts, latency, and byte volumes.
src/Equinox.EventStoreDb · high confidence
Introduce DynamoDB-backed event store
Added a new DynamoStore implementation for Equinox, enabling users to persist event streams to Amazon DynamoDB. The code defines the internal data structures (Event, Unfold, Batch) and schema mappings required to serialize domain events and snapshots into DynamoDB items, including support for encoding metadata and handling stream tips.
src/Equinox.DynamoStore · high confidence
Introduce MessageDb persistence provider for Equinox
Added a new MessageDb store implementation for Equinox, enabling event sourcing backed by a PostgreSQL database via Npgsql. This new component provides the core read/write logic, including batched message writing with optimistic concurrency control, stream reading with leader-failover support, and detailed OpenTelemetry tracing and Serilog metrics for monitoring performance and conflicts.
src/Equinox.MessageDb · high confidence
Introduce SQL Stream Store integration for Equinox
Adds a new \SqlStreamStore\ implementation that bridges Equinox with the SqlStreamStore library, enabling event sourcing persistence via SQL databases. This includes shims to map Equinox types (such as \EventBody\, \ResolvedEvent\, and \StreamEventsSlice\) to SqlStreamStore equivalents, along with comprehensive logging and metric collection for read/write operations to support observability.
src/Equinox.SqlStreamStore · high confidence
Introduce in-memory store for testing and connector examples
Adds a new \MemoryStore\ implementation that provides an in-memory event store. This serves as a lightweight target for integration testing, allowing end-to-end processing of decision flows without external dependencies, and acts as a minimal reference implementation to illustrate how to build custom store connectors for the Equinox storage interface.
src/Equinox.MemoryStore · high confidence
Introduces batching, retry, and caching primitives in Equinox.Core
The Equinox.Core library now includes new internal and public utilities to manage concurrent operations: Batching (Batch, Batcher, BatcherDictionary, BatcherCache) groups concurrent requests into batches with configurable linger times and optional semaphore-based concurrency limiting; TaskCell and TaskCellDictionary provide thread-safe async lazy caching with expiration and retry semantics; and Retry helpers offer backoff-based retry loops with a new OperationRetriesExceededException. Additionally, common Serilog logging helpers have been extracted to Internal.fs.
src/Equinox.Core · high confidence
New infrastructure module for HTTP helpers and async utilities
The \tools/Equinox.Tool/Infrastructure\ module has been added, providing core utilities for the tooling environment. This includes HTTP request/response helpers (such as \SendAsync2\ to handle timeout issues and JSON serialization via Json.Net) and async extension methods to correctly unwrap task exceptions, along with a \StringBuilder\ helper for formatted string building.
tools/Equinox.Tool/Infrastructure · high confidence
New sample store aggregates and infrastructure wiring
The Samples area now includes a complete reference implementation for a store domain, introducing four new aggregates: Cart, Favorites, SavedForLater, and ContactPreferences. This change adds the domain logic (events, folds, and services) for these aggregates, along with a centralized infrastructure layer in \Samples.Infrastructure\ that wires them into dependency injection and supports multiple backends (Memory, Cosmos, DynamoDB, EventStoreDb, and SQL Stream Store) with configurable caching and snapshotting strategies. Comprehensive FsCheck property-based tests are also added to verify the correctness and idempotency of the aggregate logic.
Samples · high confidence
Project initialization with .editorconfig and build infrastructure
The repository is initialized with standard project configuration files, including an .editorconfig for F\# formatting (4-space indentation, LF line endings), a CHANGELOG.md following Keep a Changelog format, and a SECURITY.md outlining responsible disclosure policies. Build infrastructure is established via Directory.Build.props and Directory.Build.targets, which configure MinVer for versioning, disable implicit F\# Core references for stricter dependency management, and enable static graph evaluation for faster NuGet restores. The solution structure is defined in Equinox.slnx, listing core libraries, store implementations (Cosmos, Dynamo, EventStore, etc.), samples, and tests, alongside CI configuration in azure-pipelines.yml.
(repo-wide) · high confidence
Prometheus metrics integration for DynamoDB operations
Added a new \LogSink\ component in \src/Equinox.DynamoStore.Prometheus\ that integrates with Serilog to publish operational metrics to Prometheus. This component exposes histograms and summaries for operation and round-trip latencies (in seconds) and DynamoDB Read Unit (RU) charges, along with counters for payload events and bytes. Metrics are labeled by operation type (query, transact, prune), outcome, table, and category, enabling detailed monitoring of DynamoDB store performance and resource consumption.
src/Equinox.DynamoStore.Prometheus · high confidence
Removals
Removal of EventStore persistence layer and dependencies
The \src/Foldunk.EventStore\ module has been removed, deleting the \EventStore.fs\ and \Infrastructure.fs\ files that implemented the \GesStreamStore\ and \GesEventStreamAdapter\ for reading and writing events to EventStore. The associated \paket.references\ file is also deleted, removing the \EventStore.Client\, \FSharp.Control.AsyncSeq\, and \Serilog\ dependencies from this project.
src/Foldunk.EventStore · high confidence
Behavioural changes
CosmosStore adopts JsonElement for event bodies and introduces explicit encoding fields
The CosmosStore now stores event and unfold bodies as \JsonElement\ rather than raw strings or bytes, and introduces explicit \D\ and \M\ integer fields to denote the encoding scheme (e.g., compression) for the body and metadata respectively. This shift allows the store to handle uncompressed JSON directly while maintaining backward compatibility with previous Deflate-compressed formats via the new encoding indicators, enabling more flexible and efficient serialization within Azure Cosmos DB.
src/Equinox.CosmosStore · high confidence
Introduce EventStore logging metrics and consistency tracking
The EventStore module now includes detailed logging for read/write operations, exposing metrics such as request counts, latency, and byte throughput via a Serilog sink. It also enhances consistency handling by exposing the actual version in conflict scenarios (EsSyncResult.Conflict) and logging consistency details, improving observability for users monitoring EventStore interactions.
src/Equinox.EventStore · high confidence
New caching layer with ReadThrough support and performance optimizations
Equinox now includes a built-in caching system (Cache.fs, Caching.fs) that supports SlidingWindow, FixedTimeSpan, and ReadThrough strategies, allowing concurrent read attempts to share a single roundtrip for staleness-tolerant loads. The core decision flow has been refactored to use the new Decider and DeciderCore types, which expose Transact and TransactEx overloads that accept interpret, render, and decide functions, while removing the previous Async variants. Under the hood, the library replaces AsyncLazy and CacheCell with LazyTask and TaskCell for more efficient asynchronous gating, and introduces StopwatchInterval for precise performance measurement. These changes are accompanied by new Tracing.fs extensions for OpenTelemetry-style activity tagging (e.g., cache hits, retry counts) and a streamlined Category/Stream interface that decouples store interactions from the application-facing API.
src/Equinox · high confidence
Test coverage
Added integration tests for Cosmos and DynamoDB store access strategies and caching; Added integration tests for EventStoreDB token logic and store infrastructure; Added integration tests for MemoryStore; Added integration tests for the onSync projection mechanism; Added tests for Batching, LazyTask, and TaskCell components; Removed obsolete test suite and configuration.
Dependencies
Migrate samples and tests to .NET SDK-style projects and update dependencies
The sample and test project files have been converted from legacy Paket-based formats to modern .NET SDK-style .fsproj files. This migration updates the target frameworks to net6.0 for production samples and net10.0 for tests, and refreshes dependencies to use FSharp.Core 6.0.7, FsCodec 3.1.0, xunit.v3, FsCheck.Xunit.v3, and the latest Azure Cosmos and EventStore clients.
(dependencies) · high confidence
Removal of Newtonsoft.Json dependency and serialization infrastructure
The Foldunk library has removed its dependency on Newtonsoft.Json, along with the associated serialization modules (EventSum, Serialization) and the in-memory test store (MemoryStreamStore). This change eliminates the JSON encoding/decoding logic and the specific in-memory stream implementation that relied on it, likely as part of a broader effort to clean up dependencies and support newer Visual Studio/F\# versions.
src/Foldunk · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
Score
- CAI 61 → 64 (+2.8)
- Rubric changed (rubric-2026.08.19 → rubric-2026.09.15) — scores are not directly comparable.
Lenses
- Code Health 80 → 81 (+0.9)
- Architecture 100 → 95 (-4.5)
- Maturity 63 → 62 (-0.6)
- Readiness 48 → 56 (+7.8)
- Security 75 → 74 (-1.4)
- Domain Modelling 100 → 91 (-8.5)
Resolved (68)
- CartTests.verifyCorrectEventGenerationWhenAppropriate (cognitive 16) (samples/Store/Domain.Tests/CartTests.fs)
- CartTests.verifyCorrectEventGenerationWhenAppropriate (cyclomatic 19) (samples/Store/Domain.Tests/CartTests.fs)
- Duplicated block (10 lines × 2) (samples/Infrastructure/Store.fs)
- Duplicated block (10 lines × 2) (samples/Store/Integration/CartIntegration.fs)
- Duplicated block (10 lines × 2) (src/Equinox.CosmosStore/CosmosStore.fs)
- Duplicated block (10 lines × 2) (src/Equinox.CosmosStore/CosmosStore.fs)
- Duplicated block (10 lines × 3) (src/Equinox.MessageDb/MessageDb.fs)
- Duplicated block (11 lines × 2) (src/Equinox.CosmosStore/CosmosStore.fs)
- Duplicated block (11 lines × 2) (src/Equinox.CosmosStore/CosmosStore.fs)
- Duplicated block (12 lines × 2) (src/Equinox.SqlStreamStore/SqlStreamStore.fs)
- Duplicated block (15 lines × 2) (src/Equinox.EventStoreDb/EventStoreDb.fs)
- Duplicated block (18 lines × 3) (src/Equinox.SqlStreamStore/SqlStreamStore.fs)
- Duplicated block (27 lines × 2) (src/Equinox.CosmosStore/CosmosStore.fs)
- Duplicated block (5 lines × 2) (samples/Web/Program.fs)
- Duplicated block (5 lines × 2) (src/Equinox.CosmosStore.Prometheus/CosmosStorePrometheus.fs)
- Duplicated block (5 lines × 2) (src/Equinox.CosmosStore/CosmosStore.fs)
- Duplicated block (5 lines × 2) (src/Equinox.CosmosStore/CosmosStore.fs)
- Duplicated block (5 lines × 2) (src/Equinox.CosmosStore/CosmosStore.fs)
- Duplicated block (5 lines × 2) (src/Equinox.CosmosStore/CosmosStore.fs)
- Duplicated block (5 lines × 2) (src/Equinox.EventStoreDb/EventStoreDb.fs)
- …and 48 more
New (80)
- Documentation: no installation or build instructions (README.md)
- Duplicated block (10 lines × 2) (src/Equinox.CosmosStore/CosmosStore.fs)
- Duplicated block (10 lines × 2) (src/Equinox.CosmosStore/CosmosStore.fs)
- Duplicated block (10 lines × 3) (src/Equinox.EventStore/EventStore.fs)
- Duplicated block (10–11 lines × 2) (src/Equinox.EventStore/EventStore.fs)
- Duplicated block (10–11 lines × 2) (src/Equinox.EventStore/EventStore.fs)
- Duplicated block (11 lines × 2) (src/Equinox.CosmosStore/CosmosStore.fs)
- Duplicated block (12–13 lines × 2) (src/Equinox.EventStore/EventStore.fs)
- Duplicated block (14 lines × 2) (src/Equinox.CosmosStore.Prometheus/CosmosStorePrometheus.fs)
- Duplicated block (14–16 lines × 2) (src/Equinox.CosmosStore/CosmosStore.fs)
- Duplicated block (14–19 lines × 3) (src/Equinox.EventStore/EventStore.fs)
- Duplicated block (15 lines × 2) (src/Equinox.EventStore/EventStore.fs)
- Duplicated block (16 lines × 2) (samples/Infrastructure/Store.fs)
- Duplicated block (16 lines × 2) (src/Equinox.CosmosStore/CosmosStore.fs)
- Duplicated block (17 lines × 3) (src/Equinox.EventStore/EventStore.fs)
- Duplicated block (17 lines × 4) (src/Equinox.EventStore/EventStore.fs)
- Duplicated block (19–20 lines × 2) (src/Equinox.EventStore/EventStore.fs)
- Duplicated block (20–21 lines × 2) (src/Equinox.EventStore/EventStore.fs)
- Duplicated block (24 lines × 2) (src/Equinox.EventStore/EventStore.fs)
- Duplicated block (31 lines × 2) (src/Equinox.CosmosStore/CosmosStore.fs)
- …and 60 more
Changes since last survey
- 2 commits — 2 feature/other, 0 fixes
By area
- (root) — 2 commits
Notable commits
- change: chore(Postgres): override vulernable default
- change: deps(DynamoStore): FSharp.AWS.DynamoDB 0.13.2-beta (#497)
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
jet/equinox was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 22 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit 27849463b6fd2568310ecacbe5912fa332521e4e — the exact code this score is about.
- Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-b84573e22831.