Skip to content

What is Hapnd?

Hapnd is a managed event sourcing platform that eliminates the infrastructure complexity traditionally required to build event-sourced systems. Engineers upload C# domain logic, append events through an SDK, and receive computed state back immediately — with zero infrastructure to provision, no message brokers to manage, and no projection engines to build.

The core promise: upload C# code, it just works. Zero configuration. Zero manual deployment steps. Zero compromises on security.

Building an event-sourced system from scratch typically requires:

  • Message infrastructure — Kafka, RabbitMQ, or EventStoreDB clusters to provision and maintain
  • Projection engines — Custom code to subscribe to event streams, apply events to read models, handle failures, and manage checkpoints
  • Snapshot management — Logic to periodically snapshot aggregate state so replaying from the beginning of time doesn’t become a performance problem
  • Replay mechanisms — The ability to rebuild projections from historical events when logic changes
  • Concurrency control — Optimistic concurrency to prevent lost updates across distributed writes
  • Multi-tenancy — Isolation guarantees if serving multiple customers from the same infrastructure
  • Security hardening — Ensuring customer code can’t escape its sandbox in a shared environment

Each of these is a significant engineering effort. Together, they represent months of work before any domain logic gets written. Hapnd collapses all of this into a single platform where the only thing an engineer writes is their domain logic.

Hapnd follows a progressive capability model. Start simple and add capabilities as you need them.

Append immutable facts about things that happened. Events are stored in per-aggregate streams with monotonically increasing version numbers. This is your source of truth — everything else is derived.

var result = await hapnd.Aggregate("order_123")
.Append(new OrderPlaced { CustomerId = "cust_456" });

Write a C# class that computes state from events. Bind it to an aggregate type, and every event append returns the computed state synchronously in the response. Think of it as a fold: (State, Event) → New State.

public class OrderReducer : IReducer<OrderState>
{
public OrderState Apply(OrderState? state, Event @event)
{
state ??= new OrderState();
return @event.Type switch
{
"OrderPlaced" => state with { CustomerId = @event.GetData<OrderPlacedData>().CustomerId },
"ItemAdded" => state with { Total = state.Total + @event.GetData<ItemAddedData>().Price },
_ => state
};
}
}

Build asynchronous read models across all aggregates. Same interface as reducers, but executed via a queue after events are appended. Hapnd automatically replays historical events and then processes new events as they arrive.

Get notified when projection state changes. Three delivery mechanisms: webhooks (HTTP push with HMAC-SHA256 signatures), WebSocket streaming (real-time), or REST polling (cursor-based).

ComponentChoiceWhy
Cloud platformCloudflare WorkersEdge-native, no cold starts, global distribution
Event storageDurable Objects + SQLiteStrong consistency per aggregate, co-located storage and compute
Code execution.NET 10 + RoslynEnterprise C# ecosystem, compile-time security via semantic analysis
SDK resiliencePollyIndustry-standard .NET resilience library
RegionLondon (WEUR)All infrastructure co-located for minimal latency

Hapnd runs your code through four security layers:

  1. Semantic allowlist at compile-time — Roslyn analyses your code and only permits explicitly allowed APIs. This is an inverted model: everything is blocked unless specifically permitted.
  2. DLL signature verification at load-time — Compiled assemblies are signed with ECDSA P-256. The container verifies signatures before loading any assembly.
  3. Environment variable stripping at runtime — Your code cannot access platform secrets.
  4. Container isolation — Non-root user, Alpine-based, CPU/memory limits, 5-second execution timeout.
OperationTypical Latency
Event append (no reducer)~15–30ms
Event append (with reducer)~200–500ms
State query~15–30ms

Reducer latency includes container invocation. For high-throughput scenarios where immediate state isn’t needed, append without a reducer bound and query state separately.