Here's my five latest blog posts - or you can browse a complete archive of all my posts since 2008.

What The Fork Is Going On?

I got two emails recently that have weighed heavily on my mind.

One was from a restaurant booking service called The Fork. On Saturday afternoon, I had used their service to try to book a table for dinner at Garlic & Shots, a legendary rock’n’roll bar in Stockholm. I tried calling them first: no answer, but hey, they’re probably just not open yet, and there’s a link on their website to reserve a table. 10 people, 7pm, email, phone number, confirm… “your reservation is pending”.

I hate “pending”. You can’t do anything with pending. “Hey, is there a dinner plan?” “Yeah. Or maybe no. A reservation is pending.” I suspect even Schrödinger’s cat would baulk at dinner being in some sort of unresolved quantum state.

OK, the place doesn’t open until 5pm, maybe they’ll confirm it then. 5pm comes and goes, no confirmation. I give them a call. A recorded voice says “Welcome!” - in Swedish - and then disconnects the call. This happens three times. There is no option in The Fork app to talk to a human, make a phone call, or anything of that nature. Finally I figure it’s not that far away, I get on the metro, head over, and talk to an actual human. They’ve been very busy: Iron Maiden has just played two arena shows in Stockholm, the city has been wall-to-wall metal fans for three days, and they’ve basically drunk all the beer in every rock bar in town - but no problem; they can take us for dinner. Might be 14 people, might be 8pm rather than 7pm… no problem at all. We have a delightful evening there. So. Much. Garlic.

Sunday 15th June, around 11am, I’m on the train from Stockholm to Helsingborg, and I get an email from The Fork confirming my restaurant booking: 10 people, 7pm, on Saturday 14th.

I do not know what kind of mind is required to develop, test, launch, and support a service that will confirm a restaurant reservation the day after the meal has taken place. I also strongly suspect that the proprietors of Garlic & Shots couldn’t honestly give half a microbollocks what The Fork is doing, but at some point some smooth-talking sales person probably said “no, it’s fine, we’ll handle all your reservations for you” and they just went “ok, whatever, now buy a drink or get out of my bar” and now it’s just a thing.

The next email was from His Majesty’s Revenue and Customs, informing me that there was an important message in my online tax account. They cannot, of course, tell me what the message says, or what it’s about, or even include a link directly to it. “Security reasons”.

An “important message” could actually be important. Not important like “there has been an update to the Netflix Terms & Conditions” important. Important like “you owe us money; pay up or go to jail” important.

So I open a browser, go to HMRC’s website, sign in with my Unique Taxpayer Reference, go through the multifactor authentication, go into my tax account, and sure enough, there’s an important message. I have a new tax statement. OK, cool. What does it say?

Oh, no, we can’t tell you that:

Your new Self Assessment statement has been prepared. You’ll be able to view it online within 4 working days.

So there you go. Two emails. One confirming a restaurant reservation that already happened two days earlier, the other telling me that I need to sign in to a website to see another message telling me that the thing they actually want to tell me isn’t ready yet but I should keep checking back because it’ll be there within four working days.

All you folks out there who think that coding is the hard part, and AI is going to revolutionise software development because it’ll replace the slow, unreliable human programmers with artificial intelligence that cranks out millions of lines of bug-free code in seconds? No. These emails didn’t get sent at the wrong time because of bugs in the code, or because scheduling email delivery is a hard problem and the developers couldn’t quite get it working in time. No, sending email to the right person, at the right time, is a solved problem. It’s been solved for decades. But choosing what that right time is? Identifying the situation where maybe asynchronous communication and pending reservations isn’t actually the best way to solve a problem? No, those require actual human intelligence, which is rapidly closing in on astatine’s long-held status as the rarest naturally occurring element on planet Earth.

I got two stupid pointless emails because somewhere behind them there are stupid pointless humans making stupid pointless decisions. Not programmers. In fact, most of the programmers I know would take one look at the ticket asking them to send an email saying “hey, your new tax statement is ready but you can’t read it yet” and go straight back to the product owner saying “um… how about we wait until the statement is actually available and then send the email?”

On the other hand, any startups out there using AI to replace their product owners and keeping all their human developers? Give me a call, I’ll come work for you. It would be lovely to be able to provide a bit of additional context and get a feature request instantly updated to something more sensible without causing a major political incident in the process.

Oh, and if you don’t know how to make sure email gets sent to the right person at the right time, I do that too. I made an entire course about it: Sending Email with .NET: From Zero to Hero, it’s on Dometrain, and they’re having a summer sale right now so it’s 30% off.

"What The Fork Is Going On?" was posted by Dylan Beattie on 16 June 2025 • permalink

On The Fungibility of Trains

When’s a train not a train?

I’m on my way from Antwerp to Budapest, via Amsterdam Schipol airport, on the delightfully fast and comfortable service that’s now called Eurostar but is still quite clearly a Thalys train with “Eurostar” painted on it.

Except I’m on the wrong train. I have a ticket - and a seat reservation - for the 13:30 departure to Schipol, so when a Eurostar train headed for Schipol pulled into platform 22 at Antwerp at 13:27, I went to board it. Except… no. This isn’t that train. This is train 9327. My ticket is for train 9333. There’s a Eurostar to Schipol every hour… and this one is now running exactly one hour late.

So I smiled very politely and asked if, since I had a ticket for the train that was leaving at 13:30 and I had a plane to catch, could I possibly use that ticket to board the train that was actually leaving at 13:30, and the train conductor agreed that this would probably be alright (and found me an empty seat - go Eurostar!)

The vast majority of trains in this part of the world, you don’t reserve a seat: you just buy a ticket to your destination, and it’s valid on every train headed that way. Whereas my flight to Budapest, the ticket is very clearly for a specific seat, on a specific flight, and even if by some bizarre coincidence there are delays and a different KLM flight leaves Schipol for Budapest at the exact time mine was supposed to leave, it wouldn’t occur to me to get on the wrong plane because it’s in the right place at the right time. Not without changing my ticket, anyway.

Which means Eurostar is in an interesting grey area… because although they run trains on the same rail network as EuroCity and Intercity, your Eurostar ticket is good for one seat on one train, identified by a four-digit train number… and, as I’ve learned today, the train that leaves Antwerp at 13:30 for Schipol Airport may not, in fact, be the 13:30 train to Schipol.

Next stop Budapest and CraftConf, which is going to be awesome because not only have they put together a fantastic line-up of speakers and sessions, but the conference is in a railway museum. (See? It’s all about trains today!) And then home. For a week-and-a-bit before heading to Stockholm for DevSum. I’d put hyperlinks in to all of these but I’m on my phone and you know how to Google.

"On The Fungibility of Trains" was posted by Dylan Beattie on 28 May 2025 • permalink

Sending Email with .NET: From Zero to Hero

Last month I published my first video course on Dometrain, “Sending Email with .NET: From Zero to Hero”: I just got this review from somebody who completed the course:

“⭐⭐⭐⭐⭐ Fantastic job! When I saw the course was over 9 hours, I wondered what you would talk about for that long. Now my head is swimming and it feels like 18 hours got packed into a 9 hour course. I didn’t realize how much I didn’t know about email. Thanks for putting this together.”

I didn’t set out to make a 9-hour course about sending email with .NET - I figured the course would run to 3, maybe 4 hours. But once I’d covered all the underlying standards like SMTP and MIME, modern .NET libraries like MailKit and MimeKit, tools like Mailpit, Mailtrap, ngrok, the chaos of HTML email standards and the tools like MJML that exist to work with it, how to set up all the various DNS records, SPF, DKIM, DMARC, troubleshooting, logging, sending mail from background services… there’s a lot to talk about.

The course is “Sending Email with .NET: From Zero to Hero”, you can buy it at dometrain.com, and it’s 40% off at the moment. Check it out. I think it’s awesome.

"Sending Email with .NET: From Zero to Hero" was posted by Dylan Beattie on 14 May 2025 • permalink

The Problem with “Vibe Coding”

The whole “vibe coding” thing is another reminder that quite a lot of people working in tech don’t understand the difference between programs and products.

To me, programs are “works on my machine” code. The kind of things many of us crank out a few times every week. Experiments, prototypes… that script you hacked up to rename all the MP4 files in a folder? You know the one. No error checking. Hard-coded path names. Does it work on Windows? Who cares? I’m on Linux right now and I got work to do.

I have dozens of these kinds of programs I use every day. They’re tools I use to automate bits of my work. They crash all the time (“what? Oh… that person has a backslash in the title of their presentation… interesting.”) - but that doesn’t matter; I fix them, I get the results I need, I move on. The code is just a means to an end. The result is what matters.

If you’re writing software that you’re planning to ship; to distribute to other people, perhaps even sell it to paying customers? Well, now that’s a whole different ball game.

Probably the single most important lesson I’ve learned in my career, the thing that I would argue is the hallmark of “experience”, is understanding just how much work it takes to turn a working program into a viable product. It’s why developer estimates are so notoriously optimistic - and why experienced developers are so notoriously cynical. Let’s say you crank out a bit of code that’ll take responses from a web form and add them in an Excel spreadsheet. That’s not that hard… yay! we just built a Typeform competitor in one afternoon! Except, no, you didn’t. You made one thing work one time on one computer. You haven’t considered encoding, internationalization, concurrency, authentication, telemetry, billing, branding, mobile devices, deployment. You haven’t hit any of the weird limits yet - ever had a system work brilliantly for the first 65,535 requests and then fall over? You don’t have a product. At best, you have a proof-of-concept of a good idea that, if some very smart people work very hard, might become a viable product.

One of the genuinely positive things about tools like Copilot and ChatGPT is that they empower people with minimal development experience to create their own programs. Little programs that do useful things - and that’s awesome. More power to the users.

But that’s not product development, it’s programming. They aren’t the same thing. Not even close.

"The Problem with “Vibe Coding”" was posted by Dylan Beattie on 11 April 2025 • permalink

Lunch'n'Learn with the Amsterdam Java User Group

I’m in the Netherlands. Last week was running some presentation training with a group at Info Support in Veenendaal, the weekend was catching up with friends in Amsterdam, and tomorrow I’m speaking at a student conference in Utrecht. One of the things about travelling for a living is that there’s no such thing as “out of office”, and the Todo List doesn’t stop just ‘cos you’re away for a week or two. My schedule said that today I’d be preparing examples and demos for a Zoom masterclass I’m giving on Thursday with the folks from Tech Cornwall.

A dozen or so developers sat around a table in a very Dutch-looking kitchen, drinking coffee and talking about the history of the web.

So when I got an email from Geertjan Wielenga, who runs the Amsterdam Java User Group, asking if I wanted to do a lunch’n’learn session, I naturally said “no” - mainly ‘cos I’d already have left Amsterdam for Utrecht. But, as Geerjan pointed out, the two cities are ridiculously close together… so I decided, what the hell. Usually, when I do in-person events, I bring something that’s prepared and polished: talk, slides, video… you know. What some folks call a “Dylan Talk”. Today, we did the complete opposite: all I brought with me was a list of topics I’m still working on, and after sandwiches and coffee in Geertjan’s kitchen, we spent a fun hour putting together demos, learning about the weird and wonderful edge cases of modern web standards (did you know border-radius can have EIGHT different values? 🤯)

Here’s a few links to the stuff we looked at:

and the code from the session is all up on GitHub:

Fun session. And a nice reminder that not every tech event needs to be rehearsed and polished - sometimes all you need is people, coffee and curiosity.

"Lunch'n'Learn with the Amsterdam Java User Group" was posted by Dylan Beattie on 24 March 2025 • permalink