Skip to content

ADR-005: Wolverine + Cronos — Messaging, CQRS and Scheduling

Date: 2026-02-22 Authors: Jean-Francois Meyers Scope: granit-dotnet (Granit.Wolverine, Granit.Wolverine.Postgresql, Granit.BackgroundJobs)

The platform requires:

  • Asynchronous messaging: sending commands and events between modules (domain events, integration events) with delivery guarantees
  • Transactional outbox: messages must be persisted in the same transaction as business changes (eventual consistency without loss)
  • CQRS: command/query separation with an integrated mediator
  • Background jobs: execution of recurring tasks (synchronization, cleanup, reports) with cron scheduling and multi-instance resilience
  • No external broker: for the MVP, avoid the operational complexity of a RabbitMQ or Kafka — PostgreSQL must suffice as transport

Cronos is used as the cron expression parser in the Granit.BackgroundJobs module for recurring job scheduling.

  • Wolverine (WolverineFx) as message bus, mediator and handler framework with PostgreSQL outbox
  • Cronos as cron expression parser for background job scheduling
  • License: MIT (JasperFx)
  • Outbox: native EF Core transactional (WolverineFx.EntityFrameworkCore)
  • Transport: native PostgreSQL (WolverineFx.Postgresql) — no broker required
  • Pipeline: composable middleware (validation, retry, DLQ, logging)
  • Handlers: convention-based (no interface to implement), auto-discovery
  • Integration: native FluentValidation middleware, multi-tenancy support
  • License: Apache-2.0
  • Advantage: very mature, large community, multi-transport support (RabbitMQ, Azure SB, Amazon SQS, in-memory)
  • Disadvantage: requires an external broker for production (RabbitMQ minimum), more verbose configuration, EF Core outbox available but less integrated than Wolverine, no native PostgreSQL-as-transport
  • License: Apache-2.0
  • Advantage: simple, lightweight, pure mediator pattern
  • Disadvantage: no outbox, no transport, no retry/DLQ, no scheduling — only an in-process mediator. Requires combining with another tool for asynchronous messaging
  • License: MIT
  • Advantage: outbox support, middleware pipeline
  • Disadvantage: smaller community, less comprehensive documentation, more complex configuration than Wolverine
  • License: commercial (Particular Software)
  • Advantage: complete enterprise solution, saga support, monitoring
  • Disadvantage: paid license, incompatible with the project’s OSS strategy
  • License: MIT
  • Advantage: lightweight and fast cron parser, optional seconds support, next occurrence calculation without state
  • Usage: integrated in RecurringJobAttribute and CronSchedulerAgent
  • Advantage: complete scheduler with persistence, clustering, advanced triggers
  • Disadvantage: oversized (complete scheduler when Wolverine already handles execution), responsibility duplication, heavy configuration
  • License: LGPL-3.0 (core), commercial (Pro)
  • Advantage: built-in dashboard, recurring jobs, automatic retry
  • Disadvantage: overlap with Wolverine (transport, retry, DLQ), restrictive license for advanced features
  • Advantage: simple and lightweight cron parser
  • Disadvantage: no seconds support, less modern API than Cronos, reduced maintenance
CriterionWolverineMassTransitMediatRBrighterNServiceBus
LicenseMITApache-2.0Apache-2.0MITCommercial
EF Core outboxNativeYesNoYesYes
PostgreSQL transportNativeNoN/ANoNo
Broker requiredNoYes (prod)N/AYesYes
Middleware pipelineYesYesYesYesYes
FluentValidationNativeThird-partyThird-partyNoNo
Convention-basedYesPartialNoNoNo
Multi-tenancyYesYesNoNoYes
CriterionCronosQuartz.NETHangfireNCrontab
LicenseMITApache-2.0LGPL/CommercialApache-2.0
ScopeParser onlyComplete schedulerComplete schedulerParser only
SecondsOptionalYesNoNo
WeightVery lightHeavyMediumLight
  • No external broker: PostgreSQL suffices as transport (operational simplicity)
  • Transactional outbox: zero message loss, guaranteed eventual consistency
  • Unified Wolverine pipeline: validation, retry, DLQ, logging, tracing
  • Lightweight Cronos: just a parser, orchestration is handled by Wolverine
  • MIT license for the entire stack
  • Wolverine is less known than MassTransit (smaller community)
  • Dependency on JasperFx (primary maintainer: Jeremy D. Miller)
  • If a broker need arises (RabbitMQ, Kafka), migration required (Wolverine supports RabbitMQ and Azure SB, but not Kafka natively)
  • PostgreSQL-as-transport has throughput limits vs a dedicated broker