Andrew Cairns
@acairns.co.uk
Using metaphors and analogies to explain Software Engineering in fun ways: https://youtube.com/@metaphoricallyspeaking
Staff Software Engineer. Passionate about DDD, CQRS, Event Sourcing and Distributed Systems.
Kayaking, too.
Staff Software Engineer. Passionate about DDD, CQRS, Event Sourcing and Distributed Systems.
Kayaking, too.
Why it matters:
Streaming: "Process this message and move on"
Sourcing: "Store this event forever, rebuild state from it"
Kafka with infinite retention + replay = event store.
Kafka with 7-day retention + fire-and-forget = streaming.
Same tech. Different pattern.
Know which one you're building.
Streaming: "Process this message and move on"
Sourcing: "Store this event forever, rebuild state from it"
Kafka with infinite retention + replay = event store.
Kafka with 7-day retention + fire-and-forget = streaming.
Same tech. Different pattern.
Know which one you're building.
November 3, 2025 at 9:24 AM
Why it matters:
Streaming: "Process this message and move on"
Sourcing: "Store this event forever, rebuild state from it"
Kafka with infinite retention + replay = event store.
Kafka with 7-day retention + fire-and-forget = streaming.
Same tech. Different pattern.
Know which one you're building.
Streaming: "Process this message and move on"
Sourcing: "Store this event forever, rebuild state from it"
Kafka with infinite retention + replay = event store.
Kafka with 7-day retention + fire-and-forget = streaming.
Same tech. Different pattern.
Know which one you're building.
Event Streaming: Like events flowing down the river. Consumers process them as they pass by, but they eventually fall over the waterfall at the end. Gone.
Event Sourcing: Events flowing down the river, but they're collected at the riverbank. Stored permanently.
Same river. Different approach.
Event Sourcing: Events flowing down the river, but they're collected at the riverbank. Stored permanently.
Same river. Different approach.
November 3, 2025 at 9:24 AM
Event Streaming: Like events flowing down the river. Consumers process them as they pass by, but they eventually fall over the waterfall at the end. Gone.
Event Sourcing: Events flowing down the river, but they're collected at the riverbank. Stored permanently.
Same river. Different approach.
Event Sourcing: Events flowing down the river, but they're collected at the riverbank. Stored permanently.
Same river. Different approach.
Very nice. I've been playing with Lit for a bit now, too. Was using drei when working with some threejs stuff, then found Lit when searching for alternatives.
Lovely demo. Loved /lab too 💪
Lovely demo. Loved /lab too 💪
October 30, 2025 at 10:19 AM
Very nice. I've been playing with Lit for a bit now, too. Was using drei when working with some threejs stuff, then found Lit when searching for alternatives.
Lovely demo. Loved /lab too 💪
Lovely demo. Loved /lab too 💪
Great example! Is your system event sourced?
October 24, 2025 at 3:31 PM
Great example! Is your system event sourced?
Services can react to events, for sure. It's how event-driven architecture works. Choreography is how it's often described.
Orchestration is how you'd model a Workflow. That can trigger commands and listen to events, wait for more events, invoke more commands until the Workflow is complete.
Orchestration is how you'd model a Workflow. That can trigger commands and listen to events, wait for more events, invoke more commands until the Workflow is complete.
October 24, 2025 at 2:15 PM
Services can react to events, for sure. It's how event-driven architecture works. Choreography is how it's often described.
Orchestration is how you'd model a Workflow. That can trigger commands and listen to events, wait for more events, invoke more commands until the Workflow is complete.
Orchestration is how you'd model a Workflow. That can trigger commands and listen to events, wait for more events, invoke more commands until the Workflow is complete.
Yeah, exactly. It's about the source of truth for a behaviour.
Imagine you had a counter which couldn't exceed 100. You wouldn't add an event to it's stream saying `CountIncremented`. Rules need to be protected.
You'd call something to invoke an `IncrementCount` command.
Imagine you had a counter which couldn't exceed 100. You wouldn't add an event to it's stream saying `CountIncremented`. Rules need to be protected.
You'd call something to invoke an `IncrementCount` command.
October 24, 2025 at 2:13 PM
Yeah, exactly. It's about the source of truth for a behaviour.
Imagine you had a counter which couldn't exceed 100. You wouldn't add an event to it's stream saying `CountIncremented`. Rules need to be protected.
You'd call something to invoke an `IncrementCount` command.
Imagine you had a counter which couldn't exceed 100. You wouldn't add an event to it's stream saying `CountIncremented`. Rules need to be protected.
You'd call something to invoke an `IncrementCount` command.
Keep in mind that domain events are a result of behaviour. You wouldn't push a new event directly to the stream from the outside.
A request maps to a command which, if successful, would result in a new event added to the stream.
A request maps to a command which, if successful, would result in a new event added to the stream.
October 24, 2025 at 1:39 PM
Keep in mind that domain events are a result of behaviour. You wouldn't push a new event directly to the stream from the outside.
A request maps to a command which, if successful, would result in a new event added to the stream.
A request maps to a command which, if successful, would result in a new event added to the stream.
I advocate for the workflow pattern a lot. Haven't read this article before, though.
Excellent excuse for another coffee... ☕️
Thanks for sharing!
Excellent excuse for another coffee... ☕️
Thanks for sharing!
October 24, 2025 at 1:31 PM
I advocate for the workflow pattern a lot. Haven't read this article before, though.
Excellent excuse for another coffee... ☕️
Thanks for sharing!
Excellent excuse for another coffee... ☕️
Thanks for sharing!
I’ll need to take your word for it, mate. Outside my area of experience. 😅
October 21, 2025 at 11:18 AM
I’ll need to take your word for it, mate. Outside my area of experience. 😅
Nothing jumps to my mind that I'd trust in production! 😅
I think the options are storing a checkpoint, restarting from a snapshot, or replaying from the beginning. Projections are ephemeral, though. We should feel comfortable throwing them away and rebuilding them.
I think the options are storing a checkpoint, restarting from a snapshot, or replaying from the beginning. Projections are ephemeral, though. We should feel comfortable throwing them away and rebuilding them.
October 17, 2025 at 9:03 PM
Nothing jumps to my mind that I'd trust in production! 😅
I think the options are storing a checkpoint, restarting from a snapshot, or replaying from the beginning. Projections are ephemeral, though. We should feel comfortable throwing them away and rebuilding them.
I think the options are storing a checkpoint, restarting from a snapshot, or replaying from the beginning. Projections are ephemeral, though. We should feel comfortable throwing them away and rebuilding them.
Reposted by Andrew Cairns
It is on YouTube but it was in the time of COVID so is an on-line teams type presentation thing...
youtu.be/eD7ls4KynRo
youtu.be/eD7ls4KynRo
What do you mean by “is”? - Duncan Jones - DDD Europe 2021
YouTube video by Domain-Driven Design Europe
youtu.be
October 10, 2025 at 9:27 AM
It is on YouTube but it was in the time of COVID so is an on-line teams type presentation thing...
youtu.be/eD7ls4KynRo
youtu.be/eD7ls4KynRo
I like the idea, but I've never practiced it in production.
I have a local app which displays me some metrics which is aggregate-less. But the complexity is low. I don't know how I'd handle enforcing a constraint, without duplicating it's source of truth, required by multiple commands.
wdyd?
I have a local app which displays me some metrics which is aggregate-less. But the complexity is low. I don't know how I'd handle enforcing a constraint, without duplicating it's source of truth, required by multiple commands.
wdyd?
October 10, 2025 at 9:27 AM
I like the idea, but I've never practiced it in production.
I have a local app which displays me some metrics which is aggregate-less. But the complexity is low. I don't know how I'd handle enforcing a constraint, without duplicating it's source of truth, required by multiple commands.
wdyd?
I have a local app which displays me some metrics which is aggregate-less. But the complexity is low. I don't know how I'd handle enforcing a constraint, without duplicating it's source of truth, required by multiple commands.
wdyd?
Reposted by Andrew Cairns
You can have the event chain organised as a workflow (based on an event stream) identified by an unique identifier and pass that identifier to the individual processes as a correlation id...and have them write back their doings to that event stream.
Thus your workflow is its own log.
Thus your workflow is its own log.
October 9, 2025 at 8:32 AM
You can have the event chain organised as a workflow (based on an event stream) identified by an unique identifier and pass that identifier to the individual processes as a correlation id...and have them write back their doings to that event stream.
Thus your workflow is its own log.
Thus your workflow is its own log.
Correlation IDs allow you to:
- Trace an entire business flow across services
- Subscribe to "everything about order ABC123"
- Debug distributed systems without questioning your life choices
It is a massive debuggability improvement.
- Trace an entire business flow across services
- Subscribe to "everything about order ABC123"
- Debug distributed systems without questioning your life choices
It is a massive debuggability improvement.
October 9, 2025 at 8:24 AM
Correlation IDs allow you to:
- Trace an entire business flow across services
- Subscribe to "everything about order ABC123"
- Debug distributed systems without questioning your life choices
It is a massive debuggability improvement.
- Trace an entire business flow across services
- Subscribe to "everything about order ABC123"
- Debug distributed systems without questioning your life choices
It is a massive debuggability improvement.