Skip to content
CAI
Software that uses CAICheck a score

rommsen/EventSourcing-DIY

34.6

Weak · 21 September 2026

4.9k

lines of production code

F#

primary language

6

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

This is an educational codebase that demonstrates event sourcing patterns in F\#, structured as a multi-step tutorial. It implements a domain for managing ice cream truck sales, tracking flavour stock and sales through an event store. The system features a console-based UI for interaction, separates commands from queries, and persists read models to a PostgreSQL database.

Features

Initial implementation of the Brainstorming domain and infrastructure

Introduced the core domain model for the Brainstorming module, defining the \Flavour\ type (Vanilla, Strawberry) and associated events (\Flavour\_sold\, \Flavour\_restocked\, etc.). Added infrastructure to manage an event store using a \MailboxProcessor\ for asynchronous state management, along with projection logic to track sold items and stock levels.

Brainstorming · high confidence

Initial project structure and licensing

The repository is initialized with a standard F\# solution structure containing three projects: Talk, Videos, and EventSourced. The initial commit includes an MIT license, an .editorconfig for consistent formatting, a .gitignore for build artifacts, and the foundational Types.fs file which defines core domain models like Event, Projection, and a MailboxProcessor-based EventStore implementation.

(repo-wide) · high confidence

Introduce persistent read model for tracking sold flavours

The EventSourced module now supports a persistent read model that tracks the total number of each flavour sold across all trucks. This is implemented via a new \PersistentReadmodels\ module in \Application.fs\ which uses \Npgsql.FSharp\ to insert and update records in a \flavours\_sold\ table in a PostgreSQL database. The \QueryHandlers\ module in \Application.fs\ has been updated to query this persistent store for the \FlavoursSoldOfTruck\ and \FlavoursSoldOfAll\ queries, allowing users to retrieve sold flavour counts directly from the database rather than just in-memory state.

EventSourced · high confidence

Introduce structured event sourcing with command/query separation and read models

The Videos project now implements a full event-sourcing architecture, evolving from simple in-memory event stores to a structured application layer. This includes the introduction of a CommandHandler to process commands and produce events, a QueryHandler to serve read-model queries, and ReadModel agents that project events into queryable states (such as flavour stock levels). The infrastructure supports subscribing to event streams, handling multiple query handlers, and separating domain logic (behaviour) from infrastructure concerns, enabling users to interact with the system via explicit commands and queries rather than direct event manipulation.

Videos · high confidence

Restructured Talk project into a multi-step event sourcing tutorial

The Talk directory has been reorganized to present a progressive event sourcing tutorial. The codebase is now split into four distinct steps (Step1 through Step4), each building on the previous one: Step 1 introduces basic event storage and projections; Step 2 adds stock management; Step 3 refines the domain model; and Step 4 introduces multi-aggregate support with truck-specific event streams. Each step includes its own domain, infrastructure, program logic, and unit tests, allowing users to follow the evolution of the system from a simple example to a more complex, multi-entity architecture.

Talk · high confidence

Behavioural changes

New interactive menu system for UI navigation

A new Menu module has been introduced to the UI layer, providing an interactive console-based menu system. This component handles header and footer printing, displays a list of options with visual highlighting for the selected item, and processes keyboard inputs (Up/Down arrows for navigation, Enter to select, Escape to exit). This change represents a structural refactoring of the UI's menu handling, replacing previous implementations with a more robust, loop-based navigation model.

UI · high confidence

Dependencies

Updated .NET Core target frameworks and dependencies

The project files for EventSourced, Talk, and Videos have been updated to target .NET Core 2.2, 2.0, and 2.1 respectively. The dependency manifest (paket.dependencies) and lockfile (paket.lock) have been refreshed to include Expecto, Expecto.BenchmarkDotNet, Expecto.FsCheck, Expecto.Hopac, Npgsql.FSharp, and Thoth.Json.Net, while the legacy EventSourcing\_DIY project has been removed.

(dependencies) · high confidence

Updated NuGet package cache with new dependencies

The paket restore cache has been updated to include the new \Npgsql.Fsharp\ package (version 1.9) and its dependencies, as well as an updated \Npgsql\ package (version 4.0.6) and its associated dependencies. This change reflects the addition of the F\# wrapper for Npgsql and ensures the correct versions of all transitive dependencies are cached for the build.

paket-files · 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 37 → 35 (-2.3)
  • Rubric changed (rubric-2026.08.19 → rubric-2026.09.15) — scores are not directly comparable.

Lenses

  • Code Health 85 → 82 (-3.6)
  • Architecture 100 → 95 (-4.6)
  • Maturity 9 → 11 (+2.1)
  • Readiness 26 → 26 (+0.0)
  • Security 100 → 73 (-26.7)
  • Domain Modelling 100 → 100 (+0.0)

Resolved (46)

  • Coverage not included — suite not readable by the collector
  • Dependency hygiene not measured — no packages were read
  • Duplicated block (10 lines × 2) (EventSourced/Infrastructure/EventStorage/FileStorage.fs)
  • Duplicated block (10 lines × 2) (Talk/Step4/Infrastructure4.fs)
  • Duplicated block (11 lines × 2) (Videos/Step9/Infrastructure9.fs)
  • Duplicated block (11 lines × 3) (Talk/Step4/Program4.fs)
  • Duplicated block (11 lines × 4) (Videos/Step9/Application9.fs)
  • Duplicated block (12 lines × 2) (EventSourced/Utils/List.fs)
  • Duplicated block (12 lines × 2) (Videos/Step2.fs)
  • Duplicated block (12 lines × 3) (Videos/Step9/Infrastructure9.fs)
  • Duplicated block (12 lines × 5) (EventSourced/Domain.fs)
  • Duplicated block (13 lines × 3) (Videos/Step8/Infrastructure8.fs)
  • Duplicated block (14 lines × 2) (Talk/Step2/Domain2.fs)
  • Duplicated block (14 lines × 2) (Videos/Step4.fs)
  • Duplicated block (14 lines × 2) (Videos/Step7/Infrastructure7.fs)
  • Duplicated block (15 lines × 2) (EventSourced/Infrastructure/Agent.fs)
  • Duplicated block (15 lines × 2) (Videos/Step7/Infrastructure7.fs)
  • Duplicated block (15 lines × 2) (Videos/Step9/Infrastructure9.fs)
  • Duplicated block (15 lines × 3) (Videos/Step9/Infrastructure9.fs)
  • Duplicated block (16 lines × 2) (Videos/Step7/Infrastructure7.fs)
  • …and 26 more

New (62)

  • Coverage not measured — no coverage collector is wired up
  • Duplicated block (10 lines × 3) (Talk/Step2/Program2.fs)
  • Duplicated block (11 lines × 2) (EventSourced/Infrastructure/EventStorage/FileStorage.fs)
  • Duplicated block (11 lines × 2) (Talk/Step4/Infrastructure4.fs)
  • Duplicated block (11–12 lines × 2) (Videos/Step8/Infrastructure8.fs)
  • Duplicated block (12 lines × 2) (EventSourced/Utils/List.fs)
  • Duplicated block (12 lines × 2) (Videos/Step1.fs)
  • Duplicated block (12 lines × 3) (Talk/Step1/Infrastructure1.fs)
  • Duplicated block (12 lines × 3) (Talk/Step1/Program1.fs)
  • Duplicated block (12 lines × 5) (EventSourced/Domain.fs)
  • Duplicated block (13 lines × 2) (Videos/Step8/Infrastructure8.fs)
  • Duplicated block (13–14 lines × 4) (Videos/Step6/Application6.fs)
  • Duplicated block (13–16 lines × 6) (Talk/Step2/Domain2.fs)
  • Duplicated block (14 lines × 10) (EventSourced/Domain.fs)
  • Duplicated block (14 lines × 2) (Videos/Step8/Infrastructure8.fs)
  • Duplicated block (14–15 lines × 5) (Talk/Step1/Domain1.fs)
  • Duplicated block (15 lines × 2) (EventSourced/Infrastructure/QueryHandler.fs)
  • Duplicated block (15 lines × 3) (Videos/Step7/Infrastructure7.fs)
  • Duplicated block (15–16 lines × 11) (EventSourced/Domain.fs)
  • Duplicated block (15–28 lines × 2) (Videos/Step6/Infrastructure6.fs)
  • …and 42 more

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

rommsen/EventSourcing-DIY 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 21 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 5c12d122f9c8461e7636ba6e8633a190c52f66c3 — 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.