RSSAmplifier

Blog

Jef Claes

Recent content on Jef Claes

jefclaes.beRSS feed ↗234 posts

Latest posts

Into the middlegame

Early 2025, my oldest daughter came home from school and had learned to play chess. She was so excited about the game that she even asked a board as her birthday gift. I, on the other hand, had never played chess and didn’t even know how the pieces moved. Trying to encourage and support her, I picked it up too and found my way to chess.com. I started watching chess content and the algorithm…

GES scavenging and the hidden cost of link events

Somewhere around a year ago, we started using GES in production as the primary data store of our new loyalty system. The system stores two types of data. External services push batches of dumb downed events to the loyalty system. For example: a user logged on, played a game or participated in a competition. These events are transient by nature. Once the loyalty system has processed them, they only…

Amazon Redshift - Fundamentals

Late 2017, we set out to replace and upgrade our existing reporting and analytics infrastructure with something that would be a better fit for our workloads. Keeping costs and required maintenance at a minimum would be a nice plus, making for an easy sell. After a bit of research, it was obvious Amazon Redshift had the potential to tick all the right boxes. While steadily porting the most…

Consumed in 2017

Another year, another 17 books, 6 shows and 3 movies consumed. Here’s this year’s highlights. Books The Zen and Art of Motor Cycle Maintenance The author is a tormented soul on a quest to define quality. You’re his passenger, driving shot gun on a CB77 Super Hawk, in for an exhausting intellectual journey through the high mountains of reasoning. You will often fear getting lost…

Passing the AWS Certified Solutions Architect exam

Before last week, the only certification exam I ever passed was the Microsoft .NET Framework Application Development Foundation certification. This was almost eight years ago. My manager back then thought getting certified was the best way for me to get a raise. It would be a win-win. I for one would learn something along the way, and the company would have less trouble keeping its Microsoft Gold…

Fast projections

Most EventStore client libraries allow you to subscribe to a stream by passing in a callback which is invoked when an event occurs (either a live or historic event). type Envelope = { Id : Int64 Event : Event Historic : bool } type EventOccurred = Envelope -> unit Let’s say we subscribe to a stream of a popular video service, and we want to project a read model that shows how many videos a…

From human decisions, to suggestions to automated decisions

I’ve been wanting to share this experience for a while, but it took me a while to come up with a story and example I could use in a blog post. I help out during the weekends in a small family run magic shop. I’m the third generation working in the shop. My great-grandfather always hoped that his only son would follow in his footsteps as a carpenter. But at only eighteen years old, my…

How to organize a meetup

I’ve organized a few DDDBE meetups in the past, and always succeed in forgetting something. Either someone points it out well in advance, or I end up stressing last minute. This post partly serves as a checklist for myself, but it would be a welcome side effect to also see it encourage others to help out organizing future meetups. Organizing a meetup is not rocket science, having a list of…

Printing money - hacking loyalty points

At work, we’ve all grown quite vigilant when it comes to customers trying to cheat the system. A necessary trait when working in a domain where money flows back and forth and customers are always trying to find an edge that will turn the tables. While most tend to leave this mindset at work, one colleague in particular, is always probing, trying to find cracks in the surface of everyday…

Everyone has to serve somebody, but software has to serve more than one

When people get paid to write software, we very often find some form of friction between the people that build the software and those that pay to have it built. The company I joined three years ago was no exception. When I joined, they had just launched three months ago, weren’t seeing any return on investment and prospects weren’t too bright either. I won’t lie, that first year…

Consumed in 2016

I’m keeping the tradition alive, sharing how much I’ve consumed over the last year highlighting the things that stood out. 18 books, 8 movies and 9 shows. Looks like I consumed more than other years, which probably also explains why I produced less after-hours. Books I finished the Dark Tower series after 3 years. Following Roland Deschain and his ka-tet throughout the 8 books has been…

Commands and events with JustSaying and AWS

I’ve been looking into handing a bit of our messaging infrastructure over to a managed alternative. Managing your own messaging infrastructure that should be highly available is not always an investment you want to make in this day and age. Going through the documentation and relying on experiences from some people I trust, I ended up looking at AWS and SNS / SQS . Making the Github…

My InfoQ interview on DDD, events and legacy

Seems that it’s impossible to beat the Gaussian curve of blogging frequency. On the other hand, I spent quite some of my mental blogging budget on an interview with InfoQ. I’m a bit bummed out that it’s such a large wall of text. When submitting the answers, I highlighted some snippets which should make for easier scanning. Too bad the formatting was lost when publishing it. I…

Pieter Hintjens

Writing doesn’t necessarily always come naturally to me. It often takes me days, weeks or even months of toying with an idea, before I think it’s mature enough to put it down into writing. I can’t afford that luxury this time though, I wouldn’t think of myself as much of a friend if Pieter didn’t get to read this in time. I met Pieter the first time in a bar in…

Using a batch layer for fast(er) aggregations

In the oldest system I’m maintaining right now, we have an account aggregate that, next to mutating various balances, produces immutable financial transactions. These transactions are persisted together with the aggregate itself to a relational database. The transactions can be queried by the owner of the account in an immediate consistent fashion. The table with these transactions looks…

Notifications from an event log

User notifications are a feature that came as an afterthought, but turned out to be rather easy to implement - without touching (read: breaking) existing functionality - thanks to having an immutable event log. In the domain I’m working in at the moment, we will often give users incentives to return to the website, or to extend their stay on the website. These incentives were only…

Functional one-liner for running totals in C#

Visualizing some data earlier this week I had to compute the running total of a sequence of numbers. For example, if the input sequence was [ 100; 50; 25 ] the result of the computation would be a new sequence of [ 100; 150; 175 ]. Muscle memory made me take a procedural approach, which works, but made me wonder if I could get away with less lines of code and without mutable state. static…

Consumed in 2015

I started in 2014 to keep lists of everything I consume. I’ve continued this effort throughout 2015 and can now share the items I particularly enjoyed. In 2015, I read 16 books and 3 papers, watched 3 movies and 4 shows, listened to 1 audio book and no podcasts. A lot less TV compared to 2014, but most of that time went to playing video games with some of my friends. Also a lot less time…

Visualizing event streams

In my recent talk on Evil by Design , I showed how I’ve been visualizing event streams as a means to get a better grip on how aggregates behave in production. The talk’s scope kept me from showing the code that goes together with the examples shown. Consider this post as an addendum to that talk. First off, we need a few types: a string that identifies a stream, an event containing a…

Slides from my talk "Evil by Design" at Build Stuff

Third time attending Build Stuff, first time doing a talk. I’m happy that it’s out of the way and can now just enjoy the conference, but I’m even more excited that it was well-received! The talk should have been recorded, but you can already find the abstract and slides below. Last year I ventured into the domain of (online) gambling. Given that the industry has been around since…

Defining big wins

Casinos invest a lot of energy selling the dream. One way to do this is by showing off people winning big in your casino. Everyone has seen those corny pictures of people holding human-sized cheques right? It’s a solid tactic, since empirical evidence shows that after a store has sold a large-prize winning lottery ticket, the ticket sales increase from 12 to 38% over the following weeks. If…

Bulk SQL projections with F# and type providers

Early Summer, I had to set up an integration with an external partner. They required of us to daily provide them with a relational dataset stored in SQL Server. Most, if not all of the data was temporal, append-only by nature; think logins, financial transactions.. Since the data required largely lived in an eventstore on our end, I needed fast bulk projections. Having experimented with a few…

Aspect ratio calculation

Earlier today I was writing a migration script in F# where I had to calculate the aspect ratio based on the given screen dimensions. This is one of those problems where I don’t even mind breaking my head over, but directly head over to Stackoverflow to find an accepted answer which I can just copy paste. Since I didn’t find an F# snippet I could use, I ported some JavaScript, and…

Basic casino math

In a previous series of posts, I went over the models used by casinos to spin a wheel ( spinning , manipulating the odds , clustering and near misses ). I did not yet expand on the basic mathematical models that ensure a casino makes money. Let’s pretend we are spinning the wheel again. The wheel has 5 pockets, and just one of those is the winning one. Given we will be using an unmodified…

Consumed: Queries and projections (F#)

This is the third post in my series on porting a node.js application to an F# application. So far, I’ve looked at parsing command line arguments , handling commands and storing events . Today, I want to project those events into something useful that can be formatted and printed to the console. In the original application, I only had a single query. The result of this query lists all items…

Consumed: Handling commands (F#)

As I wrote earlier , I’ve been working on porting a node.js web application to an F# console application. It’s an application I wrote to learn node.js but still use today to keep track of all the things I consume . The application is able to consume an item, to remove a consumed item and to query all consumed items. In the previous post, I parsed command line arguments into typed…

Finding unused code (F#)

Coming from C#, I’m used to the compiler warning me about unused variables. Relying on the compiler to help me with checked exceptions in F# , I noticed that unused values (and functions) would go unnoticed. Having accidentally read earlier that Haskell has a compiler flag to check for unused bindings , I looked for the F# equivalent but failed to find it, until Scott Wlaschin pointed me in…

Consumed: Parsing command line arguments (F#)

Last year, I set out to write my first node.js application; a small web application for keeping lists of everything I consume . I had something working pretty quickly, deployed it to Heroku and still find myself using it today. Since there’s very little use for having it running on a server, and because I wanted something to toy with getting better at F#, I decided to port it to an F#…

Checked errors in F#

In the land of C#, exceptions are king. By definition exceptions help us deal with “unexpected or exceptional situations that arise while a program is running”. In that regard, we’re often optimistic, overoptimistic. Most code bases treat errors as exceptional while they’re often commonplace. We are so confident about the likelyhood of things going wrong, we don’t…

Scaling promotion codes

In our system a backoffice user can issue a promotion code for users to redeem. Redeeming a promotion code, a user receives a discount on his next purchase or a free gift. A promotion code is only active for a limited amount of time, can only be redeemed a limited amount of times and can only be redeemed once per user. public bool TryRedeem(UserId userId) { if…

Domain Language: The Playthrough Bonus

Since online gambling has been regulated in Belgium, basically each eligible license holder has complemented their land based operations with an online counterpart. Being such a small country, everyone wants to secure their market share as soon as possible. The big players have been pouring tons of money in to marketing and advertising, it’s everywhere: radio, television, (online)…

Side by side

This week marked my first year at my current employer. While that event went by rather silently, one year in, a few of my observations are finally shaping up to be cast into writing. Where I used to work in the typical battery cage, I’m now part of a team of just four people, having the luxury of a big dedicated room to ourselves - a whole floor actually. The room is set up almost…

Averages are not good enough (F#)

Let’s (no pun intended) look at a set of response times of a web service. let responseTimes = [ 18 . 0 ; 21 . 0 ; 41 . 0 ; 42 . 0 ; 48 . 0 ; 50 . 0 ; 55 . 0 ; 90 . 0 ; ] People like having a single number to summarize a piece of data. The average is the most popular candidate. The average is calculated by dividing the sum of the input elements by the number of input elements. let average…

Consumed in 2014

Starting 2014, I wanted to look more closely at everything I consume. So I started keeping a list of everything I read, watch and listen to. I started off with a markdown file on Github that quikcly evolved into a good excuse to dabble with an alternative stack. I ended up writing an event sourced node.js application on top of postgres, hosted on Heroku. I could write a post on that particular…

TDD as the crack cocaine of software

The psychologist Mihaly Csikszentmihalyi popularized the term “flow” to describe states of absorption in which attention is so narrowly focused on an activity that a sense of time fades, along with the troubles and concerns of day-to-day life. “Flow provides an escape from the chaos of the quotidian,” he wrote. This is a snippet from the highly recommended book Addiction by…

Spinning the wheel: clustering and near misses

The previous post showed a simple model casinos use to manipulate the odds. Instead of relying on the physical wheel for randomness, they rely on a virtual list of indexes that maps to the physical wheel. Using that same model, it’s easy to fiddle with the virtual indexes so that they map to misses right next to the winning pocket, creating “near misses”. “Near…

Spinning the wheel: manipulating the odds

The previous post defined a basic set of data structures and functions to spin a wheel of fortune in F#. There was very little mystery to that implementation though. The physical wheel had four pockets and spinning the wheel would land you a win one out of four spins. As a casino, it’s impossible to come up with an interesting payout using this model. To juice up the pot, casinos started…

Spinning the wheel

In this post, I’ll define a basic set of data structures and functions to spin a wheel of fortune. In the next post, I’ll show you the simple model casinos use to build a bigger, more attractive pot, without touching the physical wheel and without losing money. Finally, I’ll show you how casinos tweak that model to bend the odds and create near misses. Let’s say we have a…

Hot aggregate detection using F#

Last week, I wrote about splitting a hot aggregate . Discovering that specific hot aggregate was easy; it would cause transactional failures from time to time. Long-lived hot aggregates often are an indication of a missing concept and an opportunity for teasing things apart. Last week, I took one long-lived hot aggregate and pulled smaller short-lived hot aggregates out, identifying two missing…

Splitting hot aggregates

When you visit a real casino, the constant busy-ness is overwhelming; players spamming buttons, pulling levers, spinning the wheel, gambling on the outcome of sports games, playing cards, feeding the machine, cashing out, breaking bills, ordering drinks or even buying a souvenir. A single player will easily generate a thousand transactions in one sitting. When you look at an online casino, this…

Programmatically force create a new LocalDB database

I have spent the last week working in an integration test suite that seemed to be taking ages to run its first test. I ran a profiler on the setup, and noticed a few things that were cheap to improve. The first one was how a new LocalDB database was being created. An empty database file was included into the project. When running the setup, this file would replace the existing test database.…

Print out the maximum depth of recursion allowed

Karl Seguin tweeted the following earlier this week: “An interview question I sometimes ask: Write code that prints out the maximum depth of recursion allowed.” This question is interesting for a couple of reasons. First, it’s a shorter FizzBuzz ; can the candidate open an IDE, write a few lines of code, compile and run them? And second, does he know what recursion is? Now…

Read an Event Store stream as a sequence of slices using F#

I’m slowly working on some ideas I’ve been playing around with whole Summer. Since that’s taking me to unknown territory, I guess I’ll be putting out more technical bits here in the next few weeks. Using the Event Store , I tried to read all events of a specific event type. This stream turned out to be a tad too large to be sent over the wire in one piece, leading to a…

The road to Großglockner

Sixteen days after leaving home, we’re now on our way back to Antwerp. After Croatia, we’ve driven through Slovenia, Italy, Austra and Switzerland, arriving in France to meet up with my parents for a few days. France offered us the typical vineyards and chateaux. What, next to the good company, will stick with me the most is the High Alpine road in Austria. We paid 34 euros to be…

Northbound again

Leaving Plitvice behind us , we crossed the country heading for the sea. We didn’t need to cover a lot of distance, to discover how diverse the Croatian landscape and climate is. In only two hours we went from the cold, foggy lakes and waterfalls to green meadows to dusty mountains to sunbathing coasts. We followed the coastline for a little while, strolling through old coast towns, eating…

Tolkien's inspiration

The next morning we woke up to another rainy day. We caught up with the rain in Austria and we have been following it ever since. Or the other way around. Even the locals can’t seem to stop talking about how much rain is falling. Between showers, we were able to hike the Vintgar trail. The one hour hike takes you along dangerous rapid waters, bringing you to a big waterfall. If I ever…

Porsches and a setting that sells them

With the Belgian ‘Summer’ ending, we are exploring South Eastern Europe. This trip will take us through Germany, Austria, Slovenia and Croatia. On Saturday, we stopped in Stuttgart to complete our list of visits to the three most popular European sports car museums, after visiting Lamborghini and Ferrari two years ago : the Porsche museum. In my teens, my affinity to fast cars was…

Solomon, the architect

Two junior developers who started working for the company at the same time, had been quite competitive with each other from the get-go. They had once been assigned to the same team, but because of the constant bickering, which had put a serious amount of stress on the team, one of them was pulled off the project and reassigned. A good year later, just the two of them were assigned to a new…

Thinking No Computers

The other day I happened to see a curious exchange in one of our businesses. The cashier swapped a torn, but carefully restored by taping it together again, Euro bill for a new one with the manager. Inquisitive, I asked the manager what he was planning to do with that Euro bill. “Once a month, I take all those ripped up or badly worn bills to the National Bank, and trade them for new ones.…

Paper notes: A Study and Toolkit for Asynchronous Programming in C#

The .NET framework mainly provides two models for asynchronous programming: (1) the Asynchronous Programming Model (APM), that uses callbacks, and (2) the Task Asynchronous Pattern (TAP), that uses Tasks, which are similar to the concept of futures. The Task represents the operation in progress, and its future result. The Task can be (1) queried for the status of the operation, (2) synchronized…