Live Coding Journal - Mar 25, 2026
Reflections, Learnings, and Mistakes from live coding my JitterTicket Event Sourcing application
Notes from Today’s Live Coding Session
Avro Encoding Dead-End
I spent almost 2 hours working on serializing events using Avro instead of JSON in the hope that it’d increase performance. It was a bit of a frustrating process, especially the requirements for a no-arg constructor for events, which I didn’t really want to add. After running some simple benchmarks, I realized that the JSON (de)serialization itself is probably not the performance bottleneck, and so gave up on the Avro spike. I’ll revisit performance at some point by doing more profiling of the application, but for now I need to focus on functionality that extends my learning around event-sourcing.
ConcertCompleted: Not Real? Projection = Cache
I decided to look at what it would take to add a new event, to see what the process now looks like so I can simplify it if necessary.
It turns out, the event I wanted to add, ConcertCompleted, may not make any sense.
I spent almost an hour thinking out loud about it and decided that it seemed a bit “fake” to create a whole Use Case (a Screen/UI, a Command, and an Event) just to basically “evict” the (now completed) Concert from the “Scheduled Concerts” Projection.
Since Projections are cached queries against the entire event stream, spending effort to remove an entry–when there will only be on the order of hundreds of entries–just isn’t worth it.
If I need to “garbage collect” the concerts that are no longer in the future, I can just regenerate the projection or check if I need to drop old concerts whenever a new one is added (this was option #4 on my list of ways to deal with this).
Once Projections can query for specific event types (e.g., ConcertScheduled and ConcertRescheduled, instead of all events after a checkpoint), this becomes much more feasible.
Heuristic
I think it’s important to ensure that ID-based projections don’t grow completely unbounded, i.e., there should be some event that “evicts” entries. For Summary Projections (those that do some kind of summing or aggregation across events), this doesn’t apply, since they’re like a “reduce” and would not grow nearly as fast. However, even for a Summary Projection like the Concert Sales Projection, there’s probably no business reason to keep sales information for a 3-year-old concert. (Unless you want to forecast sales of the same band for a future concert, in which case it’s fine to have it stick around.)
The thought process did reveal the biggest issue with my event-sourcing infrastructure: the focus on Aggregate IDs.
I wanted to try having an “end-of-day event” generator that Projections could consume to do things that are calendar related, but saving an event (through the EventStore) requires an ID (which becomes a primary key in the database table).
This leads to the question of, what ID would I use for such a general event?
Does this kind of event make sense from an event-sourcing system?
I think not, or at least it should not be persisted.
It might be fine if it’s treated as a Command/Trigger/Action, but such a Command would need to be executed against one (or more) actual Concerts to generate ConcertCompleted events.
Since I didn’t feel like that would be a useful next step, from either a learning or functionality standpoint, I decided to table it and move on to something else.
Next Steps
I decided to implement a new feature: the ability to set an “on sale” date/time for tickets, instead of them going on sale as soon as the concert is scheduled.
This will be interesting, not only because it’s a change in behavior, but also (as @Suigi mentioned), all of the existing scheduled concerts need to be dealt with.
And the AvailableConcerts projection (the one used to show customers what concerts they can buy tickets for) will need to change, further separating it from the ScheduledConcerts projection that is used to detect scheduling conflicts.
Join me on my next stream, which I usually do Monday through Thursday, starting at 19:00 UTC on Twitch: https://jitterted.stream.