Turning facts into something queryable
An event log on its own answers queries badly. Finding every overdue order by replaying every order's history per request would be absurd.
Watch the two patterns lock together here. Event sourcing supplies the facts, and projections turn them into shapes you can query.
A projection is a consumer that reads your events in order and maintains a view: a table of order summaries, a search index, a running revenue counter. Each one remembers its position in the log and applies new events as they arrive.
Take rebuildability as the property that changes how your team operates. Because projections are derived, you can throw one away and replay the log from the very beginning to reconstruct it.
Ship a bug that corrupts a view and you fix the code, rebuild, and lose nothing, because the truth was never in the view. Want a feature that needs the data arranged differently? Build the new projection and replay history into it, and it appears fully backfilled, including data from years before anyone thought of the feature.
Know replay's sharp edges before you need them. A log with 500 million events takes real hours to chew through, so rebuilds run against live traffic with the old view still serving reads until the new one catches up, then you cut over.
Make every projection safe to run twice, because log consumers get at-least-once delivery and will occasionally see an event again.
The tax: versioning your events
Plan for schema evolution, the deepest problem here. Events written in 2021 get replayed by 2026 code, so those old shapes must stay readable forever.
Handle it with translators that upgrade old versions as they are read, and a hard rule against breaking changes to published event types. This is the tax the pattern charges, and it is the bullet in every honest retrospective: version your events from day one.
Worked example
A food delivery company wants a fraud score based on refund patterns per customer, a feature nobody considered when the ordering system launched in 2020. Because orders are event sourced, Leila's team writes a new projection that consumes OrderPlaced, OrderRefunded, and PaymentFailed events into a per-customer stats table. They replay 800 million events from Kafka into it, which takes 9 hours on four workers at roughly 25,000 events per second. When the replay catches up to live traffic, the fraud team has five years of backfilled behavior for every customer, something a CRUD system that overwrote refund state could never produce. Two months later a bug in the scoring logic is found; they fix it, drop the table, and replay again over a weekend. Nobody sweats it, because the projection was always disposable.