Funes
A frictionless event sourcing experience for Rails developers.
About
Funes is designed to give RoR developers a frictionless experience building systems where history is as important as the present. Built with the one-person framework philosophy in mind, it honors the Rails doctrine by providing deep conceptual compression over what is usually a complex architectural pattern.
At its core is a declarative DSL that favors the interpretation of events over all the plumbing. Instead of wiring up event stores, replay loops, and serializers, you describe how each event affects state — and Funes handles persistence, ordering, concurrency, and materialization for you:
interpretation_for Debt::PaymentReceived do |state, event, _at|
state.outstanding_balance -= event.principal_amount
state.last_payment_at = event.at
state
end
By distilling the mechanics of event sourcing into just three core concepts — Events, Event Streams, and Projections — Funes handles the underlying complexity of persistence and state reconstruction for you.
Unlike traditional event sourcing frameworks that require a total shift in how you build, Funes is designed for progressive adoption. It coexists seamlessly with your existing ActiveRecord models and standard controllers. You can use Funes for a single mission-critical feature while keeping the rest of your app in plain Rails.
Why event sourcing?
In a typical Rails app, data has no past — only a present. You update! a record and the previous value is gone. Event sourcing takes a different approach: store what happened as immutable events, then derive the current state by replaying them.
This gives you:
- Complete audit trail — every state change is recorded, forever
- Temporal queries — “what was the entity state on December 1st?”, with full bi-temporal control over record time (when the system learned a fact) and actual time (when it really happened)
- Multiple interpretations — the same events, different ways to interpret state for different use cases
- Safer refactoring — rebuild any state from the event log
It’s the right choice for any application where “what was true then?” matters as much as “what is true now?”