Andrew Cairns
banner
acairns.co.uk
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.
Pinned
Composition over Inheritance: explained by retro games!

www.youtube.com/watch?v=HNzP...
Composition over Inheritance Explained by Games! #programming
YouTube video by Metaphorically Speaking
www.youtube.com
Excited for this. Cooking something new!
February 11, 2026 at 8:02 PM
Ah, sorry - I can't come into work tomorrow... I'm still gonna be watching this YouTube video. 😅
February 5, 2026 at 6:39 PM
Having a strong software development philosophy has been a super power while working with AI
February 4, 2026 at 11:10 AM
Inspired by how @dreamsofcode.bsky.social highlights elements within his videos:
February 1, 2026 at 12:27 AM
No output was faked in the making of this video
January 31, 2026 at 4:53 PM
Created a Voronoi disintegration to fracture child components into cells that scatter apart.

Planning on testing it to make a more dramatic scene transition.
January 31, 2026 at 11:22 AM
Yey, it works! 😅
January 31, 2026 at 12:42 AM
Velocity motion blur can blur asymmetrically (only behind) creating more convincing motion blur trails following the objects path.

Unlike the last example, which was using gaussian blur. It was only able to blur across x or y axis.
January 30, 2026 at 5:44 PM
Comparing one with slight motion blur, and one without.

Still playing around with the strength of the blur.
January 30, 2026 at 9:41 AM
For the longest time I've wanted to figure out how to add motion blur programatically. 🎉

I don't show it here, but I'm also setting `angle` when the movement is along the y axis.
January 29, 2026 at 9:03 PM
Shaders are so powerful! 😲
January 29, 2026 at 7:47 PM
Having so much fun!
January 29, 2026 at 6:31 PM
I’m rewriting a service in .NET and the existing service is one big PRD with Acceptance Criteria.
January 28, 2026 at 10:47 AM
Next feature I work on, I'm gonna use Opus to create the plan, then Sonnet to implement it.

I rarely switch from Opus.
January 28, 2026 at 8:03 AM
I've been using Spokenly in local-only mode with the Nvidia Parakeet dictation model.

Accuracy of spoken English has been good, and it's fast.

I do like Wispr Flow, I'll keep using that for work, but it's a solid free alternative

spokenly.app
Spokenly – Whisper-Powered Mac Dictation App | Best Voice to Text for macOS
Transform your spoken words into text on macOS with a simple click. Advanced AI text processing with local models. No data storing, no sign-ups, just pure dictation.
spokenly.app
January 27, 2026 at 5:43 PM
Argh!

Video just wasn't working. I've had to rewrite most of the first half of the script. Which means all the voiceover and animations are likely going in the bin.

But I figured it out.

Forwards!
January 13, 2026 at 10:49 PM
Love creating reusable stuff like this. The scoreboard will probably only be relevant to the new video I'm working on, but the applyGlitch() function I'm sure will be reused.

It's random, too. Looks different every time.
January 4, 2026 at 8:01 PM
Working on my next programming-related video.

I had annual leave I needed to use, or loose. So, decided to take a break from everything and focus solely on this for a full week. No other commitments.

Having so much fun!
December 9, 2025 at 3:20 PM
"We're doing Event Sourcing with Kafka!"

Maybe. Depends how you're using it.

Kafka can be an event store, but I know several teams using it just for streaming, not sourcing.

Looks similar, but it's not the same thing!

#EventSourcing #Kafka
November 3, 2025 at 9:24 AM
Your projection is broken.

This WILL happen. Plan for it!

Common strategy:
1. Build new projection (ProjectionV2)
2. Fill it from events
3. Switch traffic once caught up
4. Delete old projection

Projections are disposable.

They’re just views of events.
October 27, 2025 at 9:24 AM
Your Process Manager (thing coordinating multiple services) can ITSELF be Event Sourced!

Events IN: OrderPlaced, PaymentReceived
Events OUT: ReservationRequested, ShipmentScheduled

Orchestration with full history and testable like any aggregate

It's events all the way down
October 24, 2025 at 8:24 AM
Year 1: OrderPlaced {orderId, customerId, items}
Year 2: Needs "shippingMethod"

But, old events?
1. Upcasting: transform old events on read
2. Weak schema: new fields optional
3. Multiple event types: OrderPlacedV2

Each works:
- Weak schema = simple
- Upcasting = control
October 22, 2025 at 8:24 AM
The checkpoint problem:

Update projection → SUCCESS
Save checkpoint → CRASH

Checkpoint is now behind the data.
Restart = reprocessing.

Fix: Store checkpoint with projection data, update both in one transaction.
Either both succeed or both fail.

No inconsistency.
October 21, 2025 at 7:40 AM
Make projections idempotent

Your projection processes event 458,295 and crashes before saving checkpoint.
On restart it processes 458,295 again.

If that duplicates data, you have a problem.

Already processed? Skip it or make replaying give same result.

Design for safe replays
October 17, 2025 at 8:24 AM
Your projection crashes halfway through 1M events.

When it restarts, where does it begin?

Checkpoints solve this: periodically save "processed up to event 458,295"

Restart resumes from the checkpoint.

No checkpoint? You replay from the beginning.

Trade-off: checkpoint frequency vs replay cost.
October 16, 2025 at 8:24 AM