
I worked with my Dad’s construction crew in High School and college. On one job a lumber salesman would always come by right when we were taking a water break in the late morning and start by teasing us that we were always lounging around! I’m embarrassed to realize years later that he obviously did that on purpose to catch Dad at a good time to talk about what we were going to need next. Duh.
I think this week might have been one of the busiest weeks ever for GitHub traffic to Wolverine and I’m close to “I cannot work anymore, I just want to play pinball” levels of burned out on a Friday this week after dealing with all of that. And yes, having AI tools now makes that a lot easier mechanically, but it also makes it a lot easier for other folks to build pull requests or to analyze their own usage which has brought out plenty of issues that would probably otherwise go undetected. All told, the amount of context switching just trying to keep up with reviewing pull requests (because the buck stops here) and driving other fixes is a lot of (AI Brain Fry) work, just different than before.
Honestly, just to make me feel better, I had Claude do some research today to prove out that Wolverine actually gets much more community contribution than its .NET competitors — which I think is partially attributable to JasperFx’s “Open Core” model and partially because Wolverine is actually a much larger, more ambitious tool set in many ways than MassTransit or NServiceBus is (HTTP endpoints, more multi-tenancy options, quite a bit more modular monolith support, supporting an absurd number of messaging brokers, and far more options for simplifying application code being prime examples).
I’m focusing on pull requests here, and specifically on pull requests from people who are not part of the core team or on the payroll of the company behind the tool. Issues, Discord questions, and reproductions matter a great deal too (more on that later), but a merged pull request is the least ambiguous signal I know of that somebody outside the project cared enough to roll up their sleeves.
The numbers
Merged pull requests from outside contributors, October 2024 through October 2026:
| Project | Community PRs merged | Distinct community contributors | Came back for a 2nd PR | PRs over 500 lines |
|---|---|---|---|---|
| Wolverine | 397 | 154 | 64 | 52 |
| Brighter | 230 | 29 | 18 | 88 |
| MassTransit | 55 | 43 | 7 | 3 |
| NServiceBus | 15 | 5 | 1 | 0 |
| MediatR | 10 | 6 | 2 | 0 |
And the trend, year over year:
| Project | Oct 2024 to Oct 2025 | Oct 2025 to Oct 2026 |
|---|---|---|
| Wolverine | 116 PRs / 63 people | 281 PRs / 110 people |
| Brighter | 83 PRs / 11 people | 147 PRs / 22 people |
| MassTransit | 50 PRs / 39 people | 5 PRs / 4 people |
| NServiceBus | 4 PRs / 3 people | 11 PRs / 3 people |
| MediatR | 8 PRs / 5 people | 2 PRs / 2 people |
A few things jump out at me:
- 154 different people outside the core team got code or docs merged into Wolverine in two years. That’s more than three times the next closest tool in this list, and it nearly doubled from the first year to the second
- 64 of those folks came back and did it again. To me that’s the number that says the most about whether contributing to a project is a pleasant experience
- The median community pull request to Wolverine was merged about 21 hours after it was opened, and roughly four out of five community pull requests that get opened end up merged
- Brighter deserves a real tip of the hat here. It has a smaller contributor base than Wolverine, but a very committed one, and its community pull requests tend to be big
- The MassTransit and MediatR numbers fall off a cliff in the second year, which lines up with both tools moving to commercial licensing in 2025. I’m not taking a shot at anybody for that, building a sustainable business around OSS is hard and I’ve had to make my own choices there. But it does change what “community contribution” looks like for those tools going forward
For my part, I’m genuinely impressed with Brighter and I didn’t realize that it was nearly that active, so hat’s off to Ian and their community.
Obviously, MassTransit and NServiceBus are mostly maintained by actual employees, but so is Wolverine (mostly me, but also Babu). And MediatR is small and mature, so you wouldn’t expect too much traffic there.
Where the community has made Wolverine better
Raw counts are one thing. What I actually care about is that big, important chunks of Wolverine exist because somebody outside of JasperFx Software built them or pushed for them. Here are some of the recent themes.
Deduplication with a response, just this week
Wolverine 6.45 added [DeduplicatedWithResponse], which gives you Stripe-style idempotency keys on HTTP endpoints where a repeated request gets the first response back instead of a bare “duplicate” refusal. That was Laurence Gillian‘s idea, Laurence’s issue, and then Laurence’s pull request, which weighed in at just under 4,000 lines with tests and documentation. Laurence followed that up with two more fixes for cases where a deduplication claim outlived a request that did no work.
In the same week, alesdvorakcz fixed the mark-as-handled path so it matches the whole inbox identity inside the caller’s transaction and releases ownership of handled rows, and Marko Lahma found and fixed an inline retry that was holding onto the failed attempt’s outgoing messages. That’s three different people hardening the same corner of the idempotency story in about four days.
Native AOT
I’ll be honest that I didn’t expect AOT to matter much for a tool that was built around runtime code generation. The community has been steadily telling me otherwise. This one hasn’t been pull request driven so much as driven by people actually trying it and writing up exactly where it fell over:
- RaySinner reported a set of Native AOT startup crashes on Linux across both JasperFx and Wolverine
- Derek Choate followed that up with the proposal to emit
[DynamicDependency]rooting straight from the generated code - Christian Bergum Bergersen tracked down generic frame types that were still being closed reflectively under
TypeLoadMode.Static, first in the event registration path and then in HTTP chain building. The first of those shipped in 6.45, and the second is in flight right now with an honest to goodness Native AOT smoke test for the HTTP path
Not every valuable contribution is a pull request. A precise issue from somebody running a real AOT build is worth more to me than most pull requests.
EF Core and multi-tenancy
I’d like the number of EF Core features we don’t support to be zero and continue to make Wolverine friendlier to EF Core users because that’s always going to be where most of the .NET community is. Some recent highlights:
- Ali Yuksekkaya filed the three issues that touched off last month’s EF Core sweep, and this week landed a 1,500 line first pull request fixing step-method
[Entity]loading, query plans, and multi-tenantDbContextresolution. Three of the seven bugs it fixed were silent data loss - PerfectlyNormal fixed a missing transaction commit for multi-tenanted EF Core
- Geoffrey Marc made domain event scraping work on the managed multi-tenancy commit path and made tenanted message stores honor
MessageStoreRole - Julien Mounier added optimistic concurrency for EF Core backed sagas, and Ferdavs Majitov and Artyom both improved how the outbox lines up with EF Core’s own transaction model
Whole transports and subsystems
This is the part that still surprises me when I look at the list. A lot of what’s on the Wolverine feature matrix arrived as a community pull request:
- GCP Pub/Sub from Jay Lilja Zahiri
- Amazon SNS from Luis Villalaz
- Redis Streams from James Connor
- NATS, including JetStream, from 0xDon
- The HTTP transport, CloudEvents over HTTP, and Redis scheduling from Sandeep Desai
- An Oracle external table transport from Trasvi
- gRPC support from Erik Shafer — that’s cheating though because Erik is a core team member!
- Native API versioning for Wolverine.HTTP from Geoffrey Marc, and the
Asp.Versioningintegration from Brandon Knotek - Message encryption, fault events, and retry jitter from BlackChepo
- DataAnnotations validation middleware from Lodewijk Sioen
- Protobuf serialization from lukedukeus
- Rate limiting from Joel Gullander
- Capacity aware agent assignment from Michael Harris
- Pulsar retry and dead letter support from Rok Povodnik
- A long run of RavenDb work from Daniel Winkler and Dan Bishop, and Kafka work from lyall-sc
- F# code generation frames from Robert
The unglamorous work
And lastly, the single most prolific outside contributor to Wolverine over the last two years is Dmytro Pryvedeniuk with 28 merged pull requests who did absolutely heroic work. It’s flaky test fixes, CI consolidation, build warnings, vulnerable dependency bumps, and resource disposal. That kind of work is exactly what makes it possible for everybody else’s pull request to get merged in under a day, and I’m very grateful for it.
Thank you
I’ve been doing OSS development for a long time now, and the thing I’m most proud of with the Critter Stack isn’t any particular feature. It’s that there’s a real community of people who use these tools hard, tell us when they break, and more and more often just send the fix. If you’re one of the 154, thank you. If you’ve been thinking about being number 155, the door’s open, and I’ll do my best to keep that 21 hour number honest.
How I counted
- Source is the GitHub GraphQL API for
JasperFx/wolverine,MassTransit/MassTransit,Particular/NServiceBus,LuckyPennySoftware/MediatR, andBrighterCommand/Brighter, counting pull requests merged between October 2, 2024 and October 2, 2026 - Bot authors (Dependabot, Renovate, and friends) are excluded everywhere
- “Community” means the author is not on the project’s core team or employed by the company behind it. For Wolverine I excluded myself, Babu Annamalai, Jaedyn, Anne Erdtsieck, and other JasperFx organization members. For MassTransit that’s Chris Patterson, for MediatR it’s Jimmy Bogard, for Brighter it’s the BrighterCommand organization members, and for NServiceBus it’s everybody I could identify as Particular Software staff from their public profile, organization membership, or commit email
- GitHub’s own “member vs contributor” flag was not reliable for this because private organization membership shows up as a plain contributor, so the staff lists were built by hand. If I’ve put somebody in the wrong bucket, tell me and I’ll fix it