Posts in Go (20 found)
Michael Lynch 1 weeks ago

Refactoring English: Month 10

Hi, I’m Michael. I’m a software developer and founder of small, indie tech businesses. I’m currently working on a book called Refactoring English: Effective Writing for Software Developers . Every month, I publish a retrospective like this one to share how things are going with my book and my professional life overall. At the start of each month, I declare what I’d like to accomplish. Here’s how I did against those goals: I did complete this successfully, but I spent too long on the post and felt somewhat underwhelmed with my final result. I wrote a first draft of a new chapter but didn’t publish it. I ended up spending more time than I planned on “The Software Essays that Shaped Me” and freelance editing clients. I was going to write this off and say that I’m not learning anything new anymore by reaching out to customers. Then, a few days ago, I heard back from a reader I’d reached out to who said he used what he learned from my book to get an article on the front page of Hacker News for the first time. So, that was pretty indisputably valuable and tells me I should be doing more of this. I brainstorm more about this below . September had a nice bump in website visitors and pre-orders. I’d like to get to the point where there’s a virtuous cycle of readers referring other readers, but I don’t think I’m there yet. Still, nice to make almost $1k for the month. In baseball, a bunt is when you hold the bat in the ball’s path rather than swinging the bat. The upside is that you’re less likely to miss, but the downside is that you won’t hit the ball very far. The best you can hope for with a bunt is making it to first base, but a bunt is almost never going to be a home run. Most of my blog posts are “swing for the fences” posts. I put in a lot of effort because I want to reach #1 on Hacker News, reddit, or search results. The problem is that my “swing for the fences” posts take me about a month to write, so if I’m publishing blog posts as I write my book, I’d have to put my book on hold for a month every time I write a blog post. I’ve been thinking about whether I could do some “bunt” posts instead. That way, I can only put my book on hold for a week rather than the whole month. I don’t want to take a topic that deserves a lot of care and just do a lazy version of it. Rather, I want to take a topic that’s easy to cover and just see how it does. My first bunt was, “I Once Appeared in The Old New Thing.” It was about an experience I had at 22 at my first real job. I didn’t have a lot of insightful things to say about it, but I thought it was an interesting story. I was able to write it in about four hours, and it felt complete for what it was. My next bunt was, “The Software Essays that Shaped Me.” I’ve seen other people share lists of their favorite software blog posts, and I thought it would be an easy, fun thing to do. Best of all, the people who appreciate good software writing might also find my book interesting. As I started to write “The Software Essays that Shaped Me,” it turned into more than just a bunt. I ended up spending almost all of September on it. I originally thought I’d list my favorite blog posts and call it a day, but that felt too boring. So, I tried to include short commentary about each post. Then, I got carried away and ended up writing commentary that was longer than the originals themselves. It took me several drafts to figure out what commentary felt interesting, and I still don’t feel like I quite succeeded. I ended up spending 17 hours on “The Software Essays that Shaped Me” and never stopped to evaluate whether it was still worth writing if it was going to be all that work. I think the post is interesting to people who read my blog. If someone I knew published a list of articles that influenced them, I’d find that interesting. But in comment threads about the post, people shared their own lists, and I found strangers’ lists totally uninteresting. Maybe I counteracted that some by investing a lot in my commentary, but I just don’t think a list of good blog posts can be all that interesting. Both posts did well. They both reached the front page of Hacker News, though they did it through the second chance pool , which feels a little like winning through TKO rather than a real knockout. It’s interesting that the results scaled almost linearly with the effort I invested, which I typically don’t find to be the case . Previously, when one of my Refactoring English posts did well on Hacker News, there was a noticeable uptick in readers purchasing the book . This time, “The Software Essays that Shaped Me” reached #2 and stayed on the front page for 11 hours, but only one person purchased. Maybe everyone seeing my post on Hacker News has already seen that I’m writing a book, so everyone who’s interested has already bought? I woke up the morning after my article had already fallen off the front page of Hacker News and suddenly realized: I never included the ad for the book! All the sample chapters on the book’s website include a little self-ad to tell the reader I’m writing a book on this topic, and they can buy early access. All the pages on the Refactoring English website are supposed to have a little self-ad on them for the book. I forgot to include the self-ad for the blog post, so the first 14k readers saw my post and had no idea I’m writing a book. D’oh! I’ve updated my blog template so that I can’t possibly forget to include the self-ad in the future. A few months ago, I decided to offer freelance editing services to help other developers improve writing on their blogs. My idea was that it’s an opportunity to make sure the way I explain concepts in my book makes sense to real people. The downside is that there’s a high cost to the editing. Each job takes me between four to seven hours, and it eats up my “hard thinking” of the day, so it’s tough to do my own writing in the same day. I also feel pressure to offer quick turnaround, even though nobody has asked me to hurry. But just knowing my own writing process, it sucks to be stuck for days waiting on feedback. At the beginning, freelance editing worked as I planned: it gave me good ideas for my book. As I do more jobs, I’m getting fewer ideas for my book. Now, most of the feedback I write is basically writing a personalized version of something I’ve already written for my book. I want to keep doing the editing, but only for authors who have read my book. I doubled my rates, so now my price for editing a blog post is $400. But I’m going to offer a 90% discount to readers who have read my book. At a 90% discount, it’s almost not worth charging at all, but I want clients to pay some amount so that they feel like they have skin in the game, too. I’ll continue to take on clients who haven’t read the book, but I want to charge enough that I feel like it’s worth the tradeoff of taking time from my book. $400 might still be too low, but we’ll see. I’m trying to figure out why I keep missing my goal of reader outreach. On its face, it doesn’t seem that hard, but it never seems like the most important thing, so I keep deferring it. There are other tasks I procrastinate because I don’t enjoy doing them, but I actually enjoy reaching out to readers. It’s fun to see what different readers are up to and how they might apply my techniques. Part of the issue is that emailing readers requires activation energy because I have to: It might help if I first gather a list of customers to email and their websites. That way, when I’m in the mood to reach out, I’m not starting from scratch every time. A few Refactoring English customers have emailed me confused because they paid but never got an email with a link to the book. I collect payment through Stripe, and Stripe redirects customers to the book’s URL after they complete payment. If the customer doesn’t notice the redirect or forgets to bookmark the page, they lose access to the book. Whenever customers tell me they can’t find the link to the book, I dig around in Stripe to look for a setting to customize post-purchase emails, give up after a few minutes, and then email the correct link to the customer. Last month, I finally sat down and searched through Stripe’s documentation and forum posts, and I can’t find any way to customize the email Stripe sends after a customer completes a one-time payment. As far as I can tell, the only option is to spin up your own web server to listen for Stripe webhooks, then send your own emails from your own email provider. All because Stripe can’t be bothered to let merchants customize any text in the payment completion emails… Setting up a web server to respond to webhooks shouldn’t be that hard for me, but it means writing code to glue together Stripe, Buttondown, and Netlify functions, and they all have their little gotchas and bugs. Especially Stripe. I’ve spent about 10 hours so far just trying to get emails to send after a customer makes a purchase, and I’m still not sure it’s working correctly. Here are the gotchas I’ve hit so far: I’m still tinkering with Hacker News Observer, a product that I still haven’t released and don’t know what to do with. For now, I’m just gathering data and using it to satisfy some curiosities about success on Hacker News. One curiosity I’ve had for a long time is whether there are times of day when it’s easier for a post to reach the front page of Hacker News, so I aggregated what percentage of posts reach the front page over the course of a day: I created a view in Hacker News observer to show front page stats by hour I initially thought I had a bug that overcounted the success rate, as the percentage of Hacker News submissions that reach the front page feels lower than 12% in my experience. Then, I looked at some random slices from the last few days, and it seems to match up. If I browse , there will typically be 2-5 stories that reached the front page. I found a 30-minute slice from a few days ago where 27% of submissions reached the front page, which is surprising. I thought that success rate would be significantly higher on the weekends, when there are fewer submissions. Weekend posts are more likely to reach the front page, but the effect is much smaller than I thought. I thought it was going to be like 5% on weekdays vs. 20% on weekends. It makes submitting on the weekend less attractive because your chances of hitting the front page are only slightly better, but if you succeed, there are substantially fewer readers. I’d like to try limiting the data to personal blogs like I do on HN Popularity Contest , as I’m curious to see if personal blogs have better chances at certain times. I’m experimenting with low-investment, low-payoff-style blog posts. I’m adjusting my strategy for freelance editing to work specifically with people who have read my book. My intuition was way off about the odds of reaching the front page of Hacker News. Result : Published “The Software Essays that Shaped Me” , which attracted 16k readers in the first three days Result : Didn’t publish anything new Result : Emailed two new readers Go to my list of pre-paid readers Look for ones that have a website (so I can say something personalized) Read through their website to learn more about them Write an email and word it carefully to avoid sounding AI-generated Stripe’s Go client library is compatible with exactly one version of the Stripe webhook API. No, the documentation doesn’t say which one. Run it and find out from the webhook failures! If you update your Stripe account to use the latest webhook API version and then resend a webhook for a previous event, Stripe still uses the old API version even though it claims to use the new version. Netlify silently converts HTTP header names to lowercase, so if you’re looking for the header, you have to look for . Instead of a normal v2 Go module , Stripe for some reason decided to make every package upgrade a source change as well, so when I upgrade from v83 to v84, I have to replace in every file that imports the Stripe package. Normally, you’d upgrade the version in one place without affecting imports. The Stripe webhook signing secret is different from your Stripe API key. Weekdays: 12.1% of submissions reach the front page. Weekends: 13.2% of submissions reach the front page. Published “The Software Essays that Shaped Me” Published “I Once Appeared in The Old New Thing” Published “Get xkcd Cartoons at 2x Resolution” Worked with two freelance clients for Refactoring English Set up a webhook handler to send post-purchase emails to Refactoring English customers Added “success by hour of day” feature to Hacker News observer Started contributing to the Jellyfin Roku client code Had a call with AirGradient to discuss improving relations between the company and community members Consider bailing if a low-investment post turns out to be high-investment. Stripe does not allow you to customize post-purchase emails. You have to do a bunch of other stuff to send your customers an email. Set up editing discounts for readers who have read the book. Create a list of early access customers to reach out to. Publish a new chapter of the book.

0 views
Kix Panganiban 1 weeks ago

Python feels sucky to use now

I've been writing software for over 15 years at this point, and most of that time has been in Python. I've always been a Python fan. When I first picked it up in uni, I felt it was fluent, easy to understand, and simple to use -- at least compared to other languages I was using at the time, like Java, PHP, and C++. I've kept myself mostly up to date with "modern" Python -- think pure tooling, , and syntax, and strict almost everywhere. For the most part, I've been convinced that it's fine. But lately, I've been running into frustrations, especially with async workflows and type safety, that made me wonder if there’s a better tool for some jobs. And then I had to help rewrite a service from Python to Typescript + Bun. I'd stayed mostly detached from Typescript before, only dabbling in non-critical path code, but oh, what a different and truly joyful world it turned out to be to write code in. Here are some of my key observations: Bun is fast . It builds fast -- including installing new dependencies -- and runs fast, whether we're talking runtime performance or the direct loading of TS files. Bun's speed comes from its use of JavaScriptCore instead of V8, which cuts down on overhead, and its native bundler and package manager are written in Zig, making dependency resolution and builds lightning-quick compared to or even Python’s with . When I’m iterating on a project, shaving off seconds (or minutes) on installs and builds is a game-changer -- no more waiting around for to resolve or virtual envs to spin up. And at runtime, Bun directly executes Typescript without a separate compilation step. This just feels like a breath of fresh air for developer productivity. Type annotations and type-checking in Python still feel like mere suggestions, whereas they're fundamental in Typescript . This is especially true when defining interfaces or using inheritance -- compared to ABCs (Abstract Base Classes) and Protocols in Python, which can feel clunky. In Typescript, type definitions are baked into the language - I can define an or with precise control over shapes of data, and the compiler catches mismatches while I'm writing (provided that I've enabled it on my editor). Tools like enforce this rigorously. In Python, even with strict , type hints are optional and often ignored by the runtime, leading to errors that only surface when the code runs. Plus, Python’s approach to interfaces via or feels verbose and less intuitive -- while Typescript’s type system feels like better mental model for reasoning about code. About 99% of web-related code is async. Async is first-class in Typescript and Bun, while it’s still a mess in Python . Sure -- Python's and the list of packages supporting it have grown, but it often feels forced and riddled with gotchas and pitfalls. In Typescript, / is a core language feature, seamlessly integrated with the event loop in environments like Node.js or Bun. Promises are a natural part of the ecosystem, and most libraries are built with async in mind from the ground up. Compare that to Python, where was bolted on later (introduced in 3.5), and the ecosystem (in 2025!) is still only slowly catching up. I’ve run into issues with libraries that don’t play nicely with , forcing me to mix synchronous and asynchronous code in awkward ways. This experience has me rethinking how I approach projects. While I’m not abandoning Python -- it’s still my go-to for many things -- I’m excited to explore more of what Typescript and Bun have to offer. It’s like discovering a new favorite tool in the shed, and I can’t wait to see what I build with it next. Bun is fast . It builds fast -- including installing new dependencies -- and runs fast, whether we're talking runtime performance or the direct loading of TS files. Bun's speed comes from its use of JavaScriptCore instead of V8, which cuts down on overhead, and its native bundler and package manager are written in Zig, making dependency resolution and builds lightning-quick compared to or even Python’s with . When I’m iterating on a project, shaving off seconds (or minutes) on installs and builds is a game-changer -- no more waiting around for to resolve or virtual envs to spin up. And at runtime, Bun directly executes Typescript without a separate compilation step. This just feels like a breath of fresh air for developer productivity. Type annotations and type-checking in Python still feel like mere suggestions, whereas they're fundamental in Typescript . This is especially true when defining interfaces or using inheritance -- compared to ABCs (Abstract Base Classes) and Protocols in Python, which can feel clunky. In Typescript, type definitions are baked into the language - I can define an or with precise control over shapes of data, and the compiler catches mismatches while I'm writing (provided that I've enabled it on my editor). Tools like enforce this rigorously. In Python, even with strict , type hints are optional and often ignored by the runtime, leading to errors that only surface when the code runs. Plus, Python’s approach to interfaces via or feels verbose and less intuitive -- while Typescript’s type system feels like better mental model for reasoning about code. About 99% of web-related code is async. Async is first-class in Typescript and Bun, while it’s still a mess in Python . Sure -- Python's and the list of packages supporting it have grown, but it often feels forced and riddled with gotchas and pitfalls. In Typescript, / is a core language feature, seamlessly integrated with the event loop in environments like Node.js or Bun. Promises are a natural part of the ecosystem, and most libraries are built with async in mind from the ground up. Compare that to Python, where was bolted on later (introduced in 3.5), and the ecosystem (in 2025!) is still only slowly catching up. I’ve run into issues with libraries that don’t play nicely with , forcing me to mix synchronous and asynchronous code in awkward ways. Sub-point: Many Python patterns still push for workers and message queues -- think RQ and Celery -- when a simple async function in Typescript could handle the same task with less overhead. In Python, if I need to handle background tasks or I/O-bound operations, the go-to solution often involves spinning up a separate worker process with something like Celery, backed by a broker like Redis or RabbitMQ. This adds complexity -- now I’m managing infrastructure, debugging message serialization, and dealing with potential failures in the queue. In Typescript with Bun, I can often just write an function, maybe wrap it in a or use a lightweight library like if I need queuing, and call it a day. For a recent project, I replaced a Celery-based task system with a simple async setup in Typescript, cutting down deployment complexity and reducing latency since there’s no broker middleman. It’s not that Python can’t do async -- it’s that the cultural and technical patterns around it often lead to over-engineering for problems that Typescript, in my opinion, solves more elegantly.

0 views
Sean Goedecke 1 weeks ago

How I influence tech company politics as a staff software engineer

Many software engineers are fatalistic about company politics. They believe that it’s pointless to get involved, because 1 : The general idea here is that software engineers are simply not equipped to play the game at the same level as real political operators . This is true! It would be a terrible mistake for a software engineer to think that you ought to start scheming and plotting like you’re in Game of Thrones . Your schemes will be immediately uncovered and repurposed to your disadvantage and other people’s gain. Scheming takes practice and power, and neither of those things are available to software engineers. It is simply a fact that software engineers are tools in the political game being played at large companies, not players in their own right. However, there are many ways to get involved in politics without scheming. The easiest way is to actively work to make a high-profile project successful . This is more or less what you ought to be doing anyway, just as part of your ordinary job. If your company is heavily investing in some new project - these days, likely an AI project - using your engineering skill to make it successful 2 is a politically advantageous move for whatever VP or executive is spearheading that project. In return, you’ll get the rewards that executives can give at tech companies: bonuses, help with promotions, and positions on future high-profile projects. I wrote about this almost a year ago in Ratchet effects determine engineer reputation at large companies . A slightly harder way (but one that gives you more control) is to make your pet idea available for an existing political campaign . Suppose you’ve wanted for a while to pull out some existing functionality into its own service. There are two ways to make that happen. The hard way is to expend your own political capital: drum up support, let your manager know how important it is to you, and slowly wear doubters down until you can get the project formally approved. The easy way is to allow some executive to spend their (much greater) political capital on your project . You wait until there’s a company-wide mandate for some goal that aligns with your project (say, a push for reliability, which often happens in the wake of a high-profile incident). Then you suggest to your manager that your project might be a good fit for this. If you’ve gauged it correctly, your org will get behind your project. Not only that, but it’ll increase your political capital instead of you having to spend it. Organizational interest comes in waves. When it’s reliability time, VPs are desperate to be doing something . They want to come up with plausible-sounding reliability projects that they can fund, because they need to go to their bosses and point at what they’re doing for reliability, but they don’t have the skillset to do it on their own. They’re typically happy to fund anything that the engineering team suggests. On the other hand, when the organization’s attention is focused somewhere else - say, on a big new product ship - the last thing they want is for engineers to spend their time on an internal reliability-focused refactor that’s invisible to customers. So if you want to get something technical done in a tech company, you ought to wait for the appropriate wave . It’s a good idea to prepare multiple technical programs of work, all along different lines. Strong engineers will do some of this kind of thing as an automatic process, simply by noticing things in the normal line of work. For instance, you might have rough plans: When executives are concerned about billing, you can offer the billing refactor as a reliability improvement. When they’re concerned about developer experience, you can suggest replacing the build pipeline. When customers are complaining about performance, you can point to the Golang rewrite as a good option. When the CEO checks the state of the public documentation and is embarrassed, you can make the case for rebuilding it as a static site. The important thing is to have a detailed, effective program of work ready to go for whatever the flavor of the month is. Some program of work will be funded whether you do this or not. However, if you don’t do this, you have no control over what that program is. In my experience, this is where companies make their worst technical decisions : when the political need to do something collides with a lack of any good ideas. When there are no good ideas, a bad idea will do, in a pinch. But nobody prefers this outcome. It’s bad for the executives, who then have to sell a disappointing technical outcome as if it were a success 4 , and it’s bad for the engineers, who have to spend their time and effort building the wrong idea. If you’re a very senior engineer, the VPs (or whoever) will quietly blame you for this. They’ll be right to! Having the right idea handy at the right time is your responsibility. You can view all this in two different ways. Cynically, you can read this as a suggestion to make yourself a convenient tool for the sociopaths who run your company to use in their endless internecine power struggles. Optimistically, you can read this as a suggestion to let executives set the overall priorities for the company - that’s their job, after all - and to tailor your own technical plans to fit 3 . Either way, you’ll achieve more of your technical goals if you push the right plan at the right time. edit: this post got some attention on Hacker News . The comments were much more positive than on my other posts about politics, for reasons I don’t quite understand. This comment is an excellent statement of what I write about here (but targeted at more junior engineers). This comment (echoed here ) references a Milton Friedman quote that applies the idea in this post to political policy in general, which I’d never thought of but sounds correct: Only a crisis—actual or perceived—produces real change. When that crisis occurs, the actions that are taken depend on the ideas that are lying around. That, I believe, is our basic function: to develop alternatives to existing policies, to keep them alive and available until the politically impossible becomes politically inevitable. There’s a few comments calling this approach overly game-playing and self-serving. I think this depends on the goal you’re aiming at. The ones I referenced above seem pretty beneficial to me! Finally, this comment is a good summary of what I was trying to say: Instead of waiting to be told what to do and being cynical about bad ideas coming up when there’s a vacumn and not doing what he wants to do, the author keeps a back log of good and important ideas that he waits to bring up for when someone important says something is priority. He gets what he wants done, compromising on timing. I was prompted to write this after reading Terrible Software’s article Don’t avoid workplace politics and its comments on Hacker News. Disclaimer: I am talking here about broadly functional tech companies (i.e. ones that are making money). If you’re working somewhere that’s completely dysfunctional, I have no idea whether this advice would apply at all. What it takes to make a project successful is itself a complex political question that every senior+ engineer is eventually forced to grapple with (or to deliberately avoid, with consequences for their career). For more on that, see How I ship projects at large tech companies . For more along these lines, see Is it cynical to do what your manager wants? Just because they can do this doesn’t mean they want to. Technical decisions are often made for completely selfish reasons that cannot be influenced by a well-meaning engineer Powerful stakeholders are typically so stupid and dysfunctional that it’s effectively impossible for you to identify their needs and deliver solutions to them The political game being played depends on private information that software engineers do not have, so any attempt to get involved will result in just blundering around Managers and executives spend most of their time playing politics, while engineers spend most of their time doing engineering, so engineers are at a serious political disadvantage before they even start to migrate the billing code to stored-data-updated-by-webhooks instead of cached API calls to rip out the ancient hand-rolled build pipeline and replace it with Vite to rewrite a crufty high-volume Python service in Golang to replace the slow CMS frontend that backs your public documentation with a fast static site I was prompted to write this after reading Terrible Software’s article Don’t avoid workplace politics and its comments on Hacker News. Disclaimer: I am talking here about broadly functional tech companies (i.e. ones that are making money). If you’re working somewhere that’s completely dysfunctional, I have no idea whether this advice would apply at all. ↩ What it takes to make a project successful is itself a complex political question that every senior+ engineer is eventually forced to grapple with (or to deliberately avoid, with consequences for their career). For more on that, see How I ship projects at large tech companies . ↩ For more along these lines, see Is it cynical to do what your manager wants? ↩ Just because they can do this doesn’t mean they want to. ↩

0 views
Anton Zhiyanov 2 weeks ago

Gist of Go: Atomics

This is a chapter from my book on Go concurrency , which teaches the topic from the ground up through interactive examples. Some concurrent operations don't require explicit synchronization. We can use these to create lock-free types and functions that are safe to use from multiple goroutines. Let's dive into the topic! Non-atomic increment • Atomic operations • Composition • Atomic vs. mutex • Keep it up Suppose multiple goroutines increment a shared counter: There are 5 goroutines, and each one increments 10,000 times, so the final result should be 50,000. But it's usually less. Let's run the code a few more times: The race detector is reporting a problem: This might seem strange — shouldn't the operation be atomic? Actually, it's not. It involves three steps (read-modify-write): If two goroutines both read the value , then each increments it and writes it back, the new will be instead of like it should be. As a result, some increments to the counter will be lost, and the final value will be less than 50,000. As we talked about in the Race conditions chapter, you can make an operation atomic by using mutexes or other synchronization tools. But for this chapter, let's agree not to use them. Here, when I say "atomic operation", I mean an operation that doesn't require the caller to use explicit locks, but is still safe to use in a concurrent environment. An operation without synchronization can only be truly atomic if it translates to a single processor instruction. Such operations don't need locks and won't cause issues when called concurrently (even the write operations). In a perfect world, every operation would be atomic, and we wouldn't have to deal with mutexes. But in reality, there are only a few atomics, and they're all found in the package. This package provides a set of atomic types: Each atomic type provides the following methods: reads the value of a variable, sets a new value: sets a new value (like ) and returns the old one: sets a new value only if the current value is still what you expect it to be: Numeric types also provide an method that increments the value by the specified amount: And the / methods for bitwise operations (Go 1.23+): All methods are translated to a single CPU instruction, so they are safe for concurrent calls. Strictly speaking, this isn't always true. Not all processors support the full set of concurrent operations, so sometimes more than one instruction is needed. But we don't have to worry about that — Go guarantees the atomicity of operations for the caller. It uses low-level mechanisms specific to each processor architecture to do this. Like other synchronization primitives, each atomic variable has its own internal state. So, you should only pass it as a pointer, not by value, to avoid accidentally copying the state. When using , all loads and stores should use the same concrete type. The following code will cause a panic: Now, let's go back to the counter program: And rewrite it to use an atomic counter: Much better! ✎ Exercise: Atomic counter +1 more Practice is crucial in turning abstract knowledge into skills, making theory alone insufficient. The full version of the book contains a lot of exercises — that's why I recommend getting it . If you are okay with just theory for now, let's continue. An atomic operation in a concurrent program is a great thing. Such operation usually transforms into a single processor instruction, and it does not require locks. You can safely call it from different goroutines and receive a predictable result. But what happens if you combine atomic operations? Let's find out. Let's look at a function that increments a counter: As you already know, isn't safe to call from multiple goroutines because causes a data race. Now I will try to fix the problem and propose several options. In each case, answer the question: if you call from 100 goroutines, is the final value of the guaranteed? Is the value guaranteed? It is guaranteed. Is the value guaranteed? It's not guaranteed. Is the value guaranteed? It's not guaranteed. People sometimes think that the composition of atomic operations also magically becomes an atomic operation. But it doesn't. For example, the second of the above examples: Call 100 times from different goroutines: Run the program with the flag — there are no races: But can we be sure what the final value of will be? Nope. and calls are interleaved from different goroutines. This causes a race condition (not to be confused with a data race) and leads to an unpredictable value. Check yourself by answering the question: in which example is an atomic operation? In none of them. In all examples, is not an atomic operation. The composition of atomics is always non-atomic. The first example, however, guarantees the final value of the in a concurrent environment: If we run 100 goroutines, the will ultimately equal 200. The reason is that is a sequence-independent operation. The runtime can perform such operations in any order, and the result will not change. The second and third examples use sequence-dependent operations. When we run 100 goroutines, the order of operations is different each time. Therefore, the result is also different. A bulletproof way to make a composite operation atomic and prevent race conditions is to use a mutex: But sometimes an atomic variable with is all you need. Let's look at an example. ✎ Exercise: Concurrent-safe stack Practice is crucial in turning abstract knowledge into skills, making theory alone insufficient. The full version of the book contains a lot of exercises — that's why I recommend getting it . If you are okay with just theory for now, let's continue. Let's say we have a gate that needs to be closed: In a concurrent environment, there are data races on the field. We can fix this with a mutex: Alternatively, we can use on an atomic instead of a mutex: The type is now more compact and simple. This isn't a very common use case — we usually want a goroutine to wait on a locked mutex and continue once it's unlocked. But for "early exit" situations, it's perfect. Atomics are a specialized but useful tool. You can use them for simple counters and flags, but be very careful when using them for more complex operations. You can also use them instead of mutexes to exit early. In the next chapter, we'll talk about testing concurrent code (coming soon). Pre-order for $10   or read online Read the current value of . Add one to it. Write the new value back to . — a boolean value; / — a 4- or 8-byte integer; / — a 4- or 8-byte unsigned integer; — a value of type; — a pointer to a value of type (generic).

0 views

The Case Against Generative AI

Soundtrack: Queens of the Stone Age - First It Giveth Before we go any further: This is, for the third time this year, the longest newsletter I've ever written, weighing in somewhere around 18,500 words. I've written it specifically to be read at your leisure — dip in and out where you'd like — but also in one go.  This is my comprehensive case that yes, we’re in a bubble, one that will inevitably (and violently) collapse in the near future. I'll also be cutting this into a four-part episode starting tomorrow on my podcast Better Offline . I deeply appreciate your time. If you like this newsletter, please think about subscribing to the premium, which I write weekly. Thanks for reading. Alright, let’s do this one last time . In 2022, a (kind-of) company called OpenAI surprised the world with a website called ChatGPT that could generate text that sort-of sounded like a person using a technology called Large Language Models (LLMs), which can also be used to generate images, video and computer code.  Large Language Models require entire clusters of servers connected with high-speed networking, all containing this thing called a GPU — graphics processing units. These are different to the GPUs in your Xbox, or laptop, or gaming PC. They cost much, much more, and they’re good at doing the processes of inference (the creation of the output of any LLM) and training (feeding masses of training data to models, or feeding them information about what a good output might look like, so they can later identify a thing or replicate it). These models showed some immediate promise in their ability to articulate concepts or generate video, visuals, audio, text and code. They also immediately had one glaring, obvious problem: because they’re probabilistic, these models can’t actually be relied upon to do the same thing every single time. So, if you generated a picture of a person that you wanted to, for example, use in a story book, every time you created a new page, using the same prompt to describe the protagonist, that person would look different — and that difference could be minor (something that a reader should shrug off), or it could make that character look like a completely different person. Moreover, the probabilistic nature of generative AI meant that whenever you asked it a question, it would guess as to the answer, not because it knew the answer, but rather because it was guessing on the right word to add in a sentence based on previous training data. As a result, these models would frequently make mistakes — something which we later referred to as “hallucinations.”  And that’s not even mentioning the cost of training these models, the cost of running them, the vast amounts of computational power they required, the fact that the legality of using material scraped from books and the web without the owner’s permission was (and remains) legally dubious, or the fact that nobody seemed to know how to use these models to actually create profitable businesses.  These problems were overshadowed by something flashy, and new, and something that investors — and the tech media — believed would eventually automate the single thing that’s proven most resistant to automation: namely, knowledge work and the creative economy.  This newness and hype and these expectations sent the market into a frenzy, with every hyperscaler immediately creating the most aggressive market for one supplier I’ve ever seen. NVIDIA has sold over $200 billion of GPUs since the beginning of 2023 , becoming the largest company on the stock market and trading at over $170 as of writing this sentence only a few years after being worth $19.52 a share . While I’ve talked about some of the propelling factors behind the AI wave — automation and novelty — that’s not a complete picture. A huge reason why everybody decided to “do AI” was because the software industry’s growth was slowing , with SaaS (Software As A Service) company valuations stalling or dropping , resulting in  the terrifying prospect of companies having to “ under promise and over deliver ” and “be efficient.” Things that normal companies — those whose valuations aren’t contingent on ever-increasing, ever-constant growth — don’t have to worry about, because they’re normal companies.  Suddenly, there was the promise of a new technology — Large Language Models — that were getting exponentially more powerful, which was mostly a lie but hard to disprove because “powerful” can mean basically anything, and the definition of “powerful” depended entirely on whoever you asked at any given time, and what that person’s motivations were.  The media also immediately started tripping on its own feet, mistakenly claiming OpenAI’s GPT-4 model tricked a Taskrabbit into solving a CAPTCHA ( it didn’t — this never happened), or saying that “ people who don’t know how to code already [used] bots to produce full-fledged games, ” and if you’re wondering what “full-fledged” means, it means “pong” and a cobbled-together rolling demo of SkyRoads, a game from 1993 . The media (and investors) helped peddle the narrative that AI was always getting better, could do basically anything, and that any problems you saw today would be inevitably solved in a few short months, or years, or, well, at some point I guess.  LLMs were touted as a digital panacea, and the companies building them offered traditional software companies the chance to plug these models into their software using an API, thus allowing them to ride the same generative AI wave that every other company was riding.  The model companies similarly started going after individual and business customers, offering software and subscriptions that promised the world, though this mostly boiled down to chatbots that could generate stuff, and then doubled down with the promise of “agents” — a marketing term that’s meant to make you think “autonomous digital worker” but really means “ broken digital product .” Throughout this era, investors and the media spoke with a sense of inevitability that they never really backed up with data. It was an era based on confidently-asserted “vibes.” Everything was always getting better and more powerful, even though there was never much proof that this was truly disruptive technology, other than in its ability to disrupt apps you were using with AI — making them worse by, for example, suggesting questions on every Facebook post that you could ask Meta AI, but which Meta AI couldn’t answer. “AI” was omnipresent, and it eventually grew to mean everything and nothing. OpenAI would see its every move lorded over like a gifted child, its CEO Sam Altman called the “ Oppenheimer of Our Age ,” even if it wasn’t really obvious why everyone was impressed. GPT-4 felt like something a bit different, but was it actually meaningful?  The thing is, Artificial Intelligence is built and sold on not just faith, but a series of myths that the AI boosters expect us to believe with the same certainty that we treat things like gravity, or the boiling point of water.  Can large language models actually replace coders? Not really, no, and I’ll get into why later in the piece. Can Sora — OpenAI’s video creation tool — replace actors or animators? No, not at all, but it still fills the air full of tension because you can immediately see who is pre-registered to replace everyone that works for them.  AI is apparently replacing workers, but nobody appears to be able to prove it! But every few weeks a story runs where everybody tries to pretend that AI is replacing workers with some poorly-sourced and incomprehensible study , never actually saying “someone’s job got replaced by AI” because it isn’t happening at scale, and because if you provide real-world examples, people can actually check. To be clear, some people have lost jobs to AI, just not the white collar workers, software engineers, or really any of the career paths that the mainstream media and AI investors would have you believe.  Brian Merchant has done excellent work covering how LLMs have devoured the work of translators , using cheap, “almost good” automation to lower already-stagnant wages in a field that was already hurting before the advent of generative AI, with some having to abandon the field, and others pushed into bankruptcy. I’ve heard the same for art directors, SEO experts, and copy editors, and Christopher Mims of the Wall Street Journal covered these last year .  These are all fields with something in common: shitty bosses with little regard for their customers who have been eagerly waiting for the opportunity to slash contract labor. To quote Merchant, “the drumbeat, marketing, and pop culture of ‘powerful AI’ encourages and permits management to replace or degrade jobs they might not otherwise have.”  Across the board, the people being “replaced” by AI are the victims of lazy, incompetent cost-cutters who don’t care if they ship poorly-translated text. To quote Merchant again, “[AI hype] has created the cover necessary to justify slashing rates and accepting “good enough” automation output for video games and media products.” Yet the jobs crisis facing translators speaks to the larger flaws of the Large Language Model era, and why other careers aren’t seeing this kind of disruption. Generative AI creates outputs , and by extension defines all labor as some kind of output created from a request. In the case of translation, it’s possible for a company to get by with a shitty version, because many customers see translation as “what do these words say,” even though ( as one worker told Merchant ) translation is about conveying meaning. Nevertheless, “translation” work had already started to condense to a world where humans would at times clean up machine-generated text, and the same worker warned that the same might come for other industries. Yet the problem is that translation is a heavily output-driven industry, one where (idiot) bosses can say “oh yeah that’s fine” because they ran an output back through Google Translate and it seemed fine in their native tongue. The problems of a poor translation are obvious, but the customers of translation are, it seems, often capable of getting by with a shitty product. The problem is that most jobs are not output-driven at all, and what we’re buying from a human being is a person’s ability to think.   Every CEO talking about AI replacing workers is an example of the real problem: that most companies are run by people who don’t understand or experience the problems they’re solving, don’t do any real work, don’t face any real problems, and thus can never be trusted to solve them. The Era of the Business Idiot is the result of letting management consultants and neoliberal “free market” sociopaths take over everything, leaving us with companies run by people who don’t know how the companies make money, just that they must always make more. When you’re a big, stupid asshole, every job that you see is condensed to its outputs, and not the stuff that leads up to the output, or the small nuances and conscious decisions that make an output good as opposed to simply acceptable, or even bad.  What does a software engineer do? They write code! What does a writer do? They write words! What does a hairdresser do? They cut hair!  Yet that’s not actually the case.  As I’ll get into later, a software engineer does far more than just code, and when they write code they’re not just saying “what would solve this problem?” with a big smile on their face — they’re taking into account their years of experience, what code does, what code could do , all the things that might break as a result, and all of the things that you can’t really tell from just looking at code , like whether there’s a reason things are made in a particular way. A good coder doesn’t just hammer at the keyboard with the aim of doing a particular task. They factor in questions like: How does this functionality fit into the code that’s already here? Or, if someone has to update this code in the future, how do I make it easy for them to understand what I’ve written and to make changes without breaking a bunch of other stuff? A writer doesn’t just “write words.” They jostle ideas and ideals and emotions and thoughts and facts and feelings into a condensed piece of text, explaining both what’s happening and why it’s happening from their perspective, finding nuanced ways to convey large topics, none of which is the result of a single (or many) prompts but the ever-shifting sand of a writer’s brain.  Good writing is a fight between a bunch of different factors: structure, style, intent, audience, and prioritizing the things that you (or your client) care about in the text. It’s often emotive — or at the very least, driven or inspired by a given emotion — which is something that an AI simply can’t replicate in a way that’s authentic and believable.  And a hairdresser doesn’t just cut hair, but cuts your hair, which may be wiry, dry, oily, long, short, healthy, unhealthy, on a scalp with particular issues, at a time of year when perhaps you want to change length, at a time that fits you, in “the way you like” which may be impossible to actually write down but they get it just right. And they make conversation, making you feel at ease while they snip and clip away at your tresses, with you having to trust that they’ll get it right.  This is the true nature of labor that executives fail to comprehend at scale: that the things we do are not units of work, but extrapolations of experience, emotion, and context that cannot be condensed in written meaning. Business Idiots see our labor as the result of a smart manager saying “do this,” rather than human ingenuity interpreting both a request and the shit the manager didn’t say. What does a CEO do? Uhhh, um, well, a Harvard study says they spend 25% of their time on “people and relationships,” 25% on “functional and business unit reviews,” 16% on “organization and culture,” and 21% on “strategy,” with a few percent here and there for things like “professional development.”  That’s who runs the vast majority of companies: people that describe their work predominantly as “looking at stuff,” “talking to people” and “thinking about what we do next.” The most highly-paid jobs in the world are impossible to describe, their labor described in a mish-mash of LinkedInspiraton, yet everybody else’s labor is an output that can be automated. As a result, Large Language Models seem like magic. When you see everything as an outcome — an outcome you may or may not understand, and definitely don’t understand the process behind, let alone care about — you kind of already see your workers as LLMs.   You create a stratification of the workforce that goes beyond the normal organizational chart, with senior executives — those closer to the class level of CEO — acting as those who have risen above the doldrums of doing things to the level of “decisionmaking,” a fuzzy term that can mean everything from “making nuanced decisions with input from multiple different subject-matter experts” to, as ServiceNow Bill McDermott did in 2022 , “[make] it clear to everybody [in a boardroom of other executives], everything you do: AI, AI, AI, AI, AI.”  The same extends to some members of the business and tech media that have, for the most part, gotten by without having to think too hard about the actual things the companies are saying.  I realize this sounds a little mean, and I must be clear it doesn’t mean that these people know nothing , just that it’s been possible to scoot through the world without thinking too hard about whether or not something is true. When Salesforce said back in 2024 that its “Einstein Trust Layer” and AI would be “transformational for jobs,” the media dutifully wrote it down and published it without a second thought. It fully trusted Marc Benioff when he said that Agentforce agents would replace human workers , and then again when he said that AI agents are doing “ 30% to 50% of all the work in Salesforce itself ,” even though that’s an unproven and nakedly ridiculous statement.  Salesforce’s CFO said earlier this year that AI wouldn’t boost sales growth in 2025 . One would think this would change how they’re covered, or how seriously one takes Marc Benioff.  It hasn’t, because nobody is paying attention. In fact, nobody seems to be doing their job. This is how the core myths of generative AI were built: by executives saying stuff and the media publishing it without thinking too hard.  AI is replacing workers! AI is writing entire computer programs! AI is getting exponentially more-powerful! What does “powerful” mean? That the models are getting better on benchmarks that are rigged in their favor, but because nobody fucking explains it , regular people are regularly told that AI is “powerful.”  The only thing “powerful” about generative AI is its mythology. The world’s executives, entirely disconnected from labor and actual production, are doing the only thing they know how to — spend a bunch of money and say vague stuff about “AI being the future.” There are people — journalists, investors, and analysts — that have built entire careers on filling in the gaps for the powerful as they splurge billions of dollars and repeat with increasing desperation that “the future is here” as absolutely nothing happens. You’ve likely seen a few ridiculous headlines recently. One of the most recent, and most absurd, is that that OpenAI will pay Oracle $300 billion over four years , closely followed with the claim that NVIDIA will “invest” “$100 billion” in OpenAI to build 10GW of AI data centers , though the deal is structured in a way that means that OpenAI is paid “progressively as each gigawatt is deployed,” and OpenAI will be leasing the chips (rather than buying them outright) . I must be clear that these deals are intentionally made to continue the myth of generative AI, to pump NVIDIA, and to make sure OpenAI insiders can sell $10.3 billion of shares .   OpenAI cannot afford the $300 billion, NVIDIA hasn’t sent OpenAI a cent and won’t do so if it can’t build the data centers, which OpenAI most assuredly can’t afford to do.  NVIDIA needs this myth to continue, because in truth, all of these data centers are being built for demand that doesn’t exist, or that — if it exists — doesn’t necessarily translate into business customers paying huge amounts for access to OpenAI’s generative AI services.  NVIDIA, OpenAI, CoreWeave and other AI-related companies hope that by announcing theoretical billions of dollars (or hundreds of billions of dollars) of these strange, vague and impossible-seeming deals, they can keep pretending that demand is there, because why else would they build all of these data centers, right?   That, and the entire stock market rests on NVIDIA’s back . It accounts for 7% to 8% of the value of the S&P 500, and Jensen Huang needs to keep selling GPUs. I intend to explain later on how all of this works, and how brittle it really is. The intention of these deals is simple: to make you think “this much money can’t be wrong.” It can. These people need you to believe this is inevitable, but they are being proven wrong, again and again, and today I’m going to continue doing so.  Underpinning these stories about huge amounts of money and endless opportunity lies a dark secret — that none of this is working, and all of this money has been invested in a technology that doesn’t make much revenue and loves to burn millions or billions or hundreds of billions of dollars. Over half a trillion dollars has gone into an entire industry without a single profitable company developing models or products built on top of models. By my estimates, there is around $44 billion of revenue in generative AI this year (when you add in Anthropic and OpenAI’s revenues to the pot, along with the other stragglers) and most of that number has been gathered through reporting from outlets like The Information, because none of these companies share their revenues, all of them lose shit tons of money , and their actual revenues are really, really small. Only one member of the Magnificent Seven (outside of NVIDIA) has ever disclosed its AI revenue — Microsoft, which stopped reporting in January 2025, when it reported “$13 billion in annualized revenue,” so around $1.083 billion a month.   Microsoft is a sales MACHINE. It is built specifically to create or exploit software markets, suffocating competitors by using its scale to drive down prices, and to leverage the ecosystem that it’s created over the past few decades. $1 billion a month in revenue is chump change for an organization that makes over $27 billion a quarter in PROFITS .  Don’t worry Satya, I’ll come back to you later. “But Ed, the early days!” Worry not — I’ve got that covered .  This is nothing like any other era of tech. There has never been this kind of cash-rush, even in the fiber boom . Over a decade, Amazon spent about one-tenth of the capex that the Magnificent Seven spent in two years on generative AI building AWS — something that now powers a vast chunk of the web, and has long been Amazon’s most profitable business unit .  Generative AI is nothing like Uber , with OpenAI and Anthropic’s true costs coming in at about $159 billion in the past two years, approaching five times Uber’s $30 billion all-time burn. And that’s before the bullshit with NVIDIA and Oracle. Microsoft last reported AI revenue in January . It’s October this week. Why did it stop reporting this number, you think? Is it because the numbers are so good it couldn’t possibly let people know? As a general rule, publicly traded companies — especially those where the leadership are compensated primarily in equity — tend to brag about their successes, in part because said bragging boosts the value of the thing that the leadership gets paid in. There’s no benefit to being shy. Oracle literally made a regulatory filing to boast it had a $30 billion customer , which turned out to be OpenAI, who eventually agreed (publicly) to spend $300 billion in compute over five years .  Which is to say that Microsoft clearly doesn’t have any good news to share, and as I’ll reveal later, they can’t even get 3% of their 440 million Microsoft 365 subscribers to pay for Microsoft 365 Copilot.  If Microsoft can’t sell this shit, nobody can.  Anyway, I’m nearly done, sorry, you see, I’m writing this whole thing as if you’re brand new and walking up to this relatively unprepared, so I need to introduce another company.  In 2020, a splinter group jumped off of OpenAI, funded by Amazon and Google to do much the same thing as OpenAI but pretend to be nicer about it until they have to raise from the Middle East . Anthropic has always been better at coding for some reason, and people really like its Claude models.  Both OpenAI and Anthropic have become the only two companies in generative AI to make any real progress, either in terms of recognition or in sheer commercial terms, accounting for the majority of the revenue in the AI industry.  In a very real sense, the AI industry’s revenue is OpenAI and Anthropic. In the year where Microsoft recorded $13bn in AI revenues, $10 billion came from OpenAI’s  spending on Microsoft Azure. Anthropic burned $5.3 billion last year — with the vast majority of that going towards compute . Outside of these two companies, there’s barely enough revenue to justify a single data center. Where we sit today is a time of immense tension. Mark Zuckerberg says we’re in a bubble , Sam Altman says we’re in a bubble , Alibaba Chairman and billionaire Joe Tsai says we’re in a bubble , Apollo says we’re in a bubble , nobody is making money and nobody knows why they’re actually doing this anymore, just that they must do it immediately.  And they have yet to make the case that generative AI warranted any of these expenditures.  That was undoubtedly the longest introduction to a newsletter I’ve ever written, and the reason why I took my time was because this post demands a level of foreshadowing and exposition, and because I want to make it make sense to anyone who reads it — whether they’ve read my newsletter for years, or whether they’re only just now investigating their suspicions that generative AI may not be all it’s cracked up to be.  Today I will make the case that generative AI’s fundamental growth story is flawed, and explain why we’re in the midst of an egregious bubble. This industry is sold by keeping things vague, and knowing that most people don’t dig much deeper than a headline, a problem I simply do not have.  This industry is effectively in service of two companies — OpenAI and NVIDIA — who pump headlines out through endless contracts between them and subsidiaries or investments to give the illusion of activity.  OpenAI is now, at this point, on the hook for over a trillion dollars , an egregious sum for a company that already forecast billions in losses, with no clear explanation as to how it’ll afford any of this beyond “we need more money” and the vague hope that there’s another Softbank or Microsoft waiting in the wings to swoop in and save the day.  I’m going to walk you through where I see this industry today, and why I see no future for it beyond a fiery apocalypse.  While everybody (reasonably!) harps on about hallucinations — which, to remind you, is when a model authoritatively states something that isn’t true — but the truth is far more complex, and far worse than it seems.  You cannot rely on a large language model to do what you want. Even the most highly-tuned models on the most expensive and intricate platform can’t actually be relied upon to do exactly what you want.  A “hallucination” isn’t just when these models say something that isn’t true. It’s when they decide to do something wrong because it seems the most likely thing to do, or when a coding model decides to go on a wild goose chase, failing the user and burning a ton of money in the process.  The advent of “reasoning” models — those engineered to ‘think’ through problems in a way reminiscent of a human — and the expansion of what people are (trying) to use LLMs for demands that the definition of an AI hallucination be widened, not merely referring to factual errors, but fundamental errors in understanding the user’s request or intent, or what constitutes a task, in part because these models cannot think and do not know anything .  However successful a model might be in generating something good *once*, it will also often generate something bad, or it’ll generate the right thing but in an inefficient and over-verbose fashion. You do not know what you’re going to get each time, and hallucinations multiply with the complexity of the thing you’re asking for, or whether a task contains multiple steps (which is a fatal blow to the idea of “agents.”  You can add as many levels of intrigue and “reasoning” as you want, but Large Language Models cannot be trusted to do something correctly, or even consistently, every time. Model companies have successfully convinced everybody that the issue is that users are prompting the models wrong, and that people need to be “trained to use AI,” but what they’re doing is training people to explain away the inconsistencies of Large Language Models, and to assume individual responsibility for what is an innate flaw in how large language models work.  Large Language Models are also uniquely expensive. Many mistakenly try and claim this is like the dot com boom or Uber, but the basic unit economics of generative AI are insane. Providers must purchase tens or hundreds of thousands of GPUs each costing $50,000 a piece, and hundreds of millions or billions of dollars of infrastructure for large clusters. And that’s without mentioning things like staffing, construction, power, or water.   Then you turn them on and start losing money. Despite hundreds of billions of GPUs sold, nobody seems to make any money, other than NVIDIA, the company that makes them, and resellers like Dell and Supermicro who buy the GPUs, put them in servers, and sell them to other people.  This arrangement works out great for Jensen Huang, and terribly for everybody else.  I am going to explain the insanity of the situation we find ourselves in, and why I continue to do this work undeterred. The bubble has entered its most pornographic, aggressive and destructive stage, where the more obvious it becomes that they’re cooked, the more ridiculous the generative AI industry will act — a dark juxtaposition against every new study that says “generative AI does not work” or new story about ChatGPT’s uncanny ability to activate mental illness in people.  So, let’s start simple: NVIDIA is a hardware company that sells GPUs, including the consumer GPUs that you’d see in a modern gaming PC, but when you read someone say “GPU” within the context of AI, they mean enterprise-focused GPUs like the A100, H100, H200, and more modern GPUs like the Blackwell-series B200 and GB200 (which combines two GPUs with an NVIDIA CPU).  These GPUs cost anywhere from $30,000 to $50,000 (or as high as $70,000 for the newer Blackwell GPUs), and require tens of thousands of dollars more of infrastructure — networking to “cluster” server racks of GPUs together to provide compute, and massive cooling systems to deal with the massive amounts of heat they produce, as well as the servers themselves that they run on, which typically use top-of-the-line data center CPUs, and contain vast quantities of high-speed memory and storage. While the GPU itself is likely the most expensive single item within an AI server, the other costs — and I’m not even factoring in the actual physical building that the server lives in, or the water or electricity that it uses — add up.  I’ve mentioned NVIDIA because it has a virtual monopoly in this space. Generative AI effectively requires NVIDIA GPUs, in part because it’s the only company really making the kinds of high-powered cards that generative AI demands, and  because NVIDIA created something called CUDA — a collection of software tools that lets programmers write software that  runs on GPUs, which were traditionally used primarily for rendering graphics in games.  While there are open-source alternatives , as well as alternatives from Intel (with its ARC GPUs) and AMD (Nvidia’s main rival in the consumer space), these aren’t nearly as mature or feature-rich.  Due to the complexities of AI models, one cannot just stand up a few of these things either — you need clusters of thousands, tens of thousands, or hundreds of thousands of them for it to be worthwhile, making any investment in GPUs in the hundreds of millions or billions of dollars, especially considering they require completely different data center architecture to make them run. A common request — like asking a generative AI model to parse through thousands of lines of code and make a change or an addition — may use multiple of these $50,000 GPUs at the same time, and so if you aspire to serve thousands, or millions of concurrent users, you need to spend big. Really big.  It’s these factors — the vendor lock-in, the ecosystem, and the fact that generative AI only works when you’re buying GPUs at scale — that underpin the rise of Nvidia. But beyond the economic and technical factors, there are human ones, too.   To understand the AI bubble is to understand why CEOs do the things they do. Because an executive’s job is so vague , they can telegraph the value of their “labor” by spending money on initiatives and making partnerships. AI gave hyperscalers the excuse to spend hundreds of billions of dollars on data centers and buy a bunch of GPUs to go in them, because that, to the markets, looks like they’re doing something. By virtue of spending a lot of money in a frighteningly short amount of time, Satya Nadella received multiple glossy profiles , all without having to prove that AI can really do anything, be it a job or make Microsoft money.  Nevertheless, AI allowed CEOs to look busy, and once the markets and journalists had agreed on the consensus opinion that “AI would be big,” all that these executives had to do was buy GPUs and “do AI.”   We are in the midst of one of the darkest forms of software in history, described by many as an unwanted guest invading their products, their social media feeds, their bosses’ empty minds, and resting in the hands of monsters. Every story of its success feels bereft of any real triumph, with every literal description of its abilities involving multiple caveats about the mistakes it makes or the incredible costs of running it.  Generative AI exists for two reasons: to cost money, and to make executives look busy. It was meant to be the new enterprise software and the new iPhone and the new Netflix all at once, a panacea where software guys pay one hardware guy for GPUs to unlock the incredible value creation of the future.  Generative AI was always set up to fail, because it was meant to be everything, was talked about like it was everything, is still sold like it’s everything, yet for all the fucking hype, it all comes down to two companies: OpenAI, and, of course, NVIDIA. NVIDIA was, for a while, living high on the hog. All CEO Jensen Huang had to do every three months was saying “check out these numbers” and the markets and business journalists would squeal with glee, even as he said stuff like “ the more you buy the more you save ,” in part tipping his head to the (very real and sensible) idea of accelerated computing, but framed within the context of the cash inferno that’s generative AI, seems ludicrous.  Huang’s showmanship  worked really well for NVIDIA for a while, because for a while the growth was easy. Everybody was buying GPUs. Meta, Microsoft, Amazon, Google (and to a lesser extent Apple and Tesla) make up 42% of NVIDIA’s revenue , creating, at least for the first four, a degree of shared mania where everybody justified buying tens of billions of dollars of GPUs a year by saying “the other guy is doing it!” This is one of the major reasons the AI bubble is happening, because people conflated NVIDIA’s incredible sales with “interest in AI,” rather than everybody buying GPUs. Don’t worry, I’ll explain the revenue side a little bit later. We’re here for the long haul. Anyway, NVIDIA is facing a problem — that the only thing that grows forever is cancer .  On September 9 2025, the Wall Street Journal said that NVIDIA’s “wow” factor was fading , going from beating analyst estimates in by nearly 21% in its Fiscal Year Q2 2024 earnings to scraping by with a mere 1.52% beat in its most-recent earnings — something that for any other company, would be a good thing, but framed against the delusional expectations that generative AI has inspired, is a figure that looks nothing short of ominous. Per the Wall Street Journal: In any other scenario, 56% year-over-year growth would lead to an abundance of Dom Perignon and Huang signing hundreds of boobs , but this is NVIDIA , and that’s just not good enough. Back in February 2024, NVIDIA was booking 265% year-over-year growth , but in its February 2025 earnings, NVIDIA only grew by a measly 78% year-over-year .  It isn’t so much that NVIDIA isn’t growing , but that to grow year-over-year at the rates that people expect is insane. Life was a lot easier when NVIDIA went from $6.05 billion in revenue in Q4 FY2023 to $22 billion in revenue in Q4 FY2024 , but for it to grow even 55% year-over-year from Q2 FY2026 ( $46.7 billion ) to Q2 2027 would require it to make $72.385 billion in revenue in the space of three months, mostly from selling GPUs (which make up around 88% of its revenue).   This would put Nvidia in the ballpark of Microsoft ( $76 billion in the last quarter ) and within the neighborhood of Apple ( $94 billion in the last quarter ), predominantly making money in an industry that a year-and-a-half ago barely made the company $6 billion in a quarter.  And the market needs NVIDIA to perform, as the company makes up 8% of the value of the S&P 500 . It’s not enough for it to be wildly profitable, or have a monopsony on selling GPUs, or for it to have effectively 10x’d their stock in a few years. It must continue to grow at the fastest rate of anything ever, making more and more money selling these GPUs to a small group of companies that immediately start losing money once they plug them in.  While a few members of the Magnificent Seven could be depended on to funnel tens of billions of dollars into a furnace each quarter, there were limits , even for companies like Microsoft, which had bought over 485,000 GPUs in 2024 alone . To take a step back, companies like Microsoft, Google and Amazon make their money by either selling access to Large Language Models that people incorporate into their products, or by renting out servers full of GPUs to run inference (as said previously, the process to generate an output by a model or series of models) or train AI models for companies that develop and market models themselves, namely Anthropic and OpenAI.  The latter revenue stream of which is where Jensen Huang found a solution to that eternal growth problem: the neocloud, namely CoreWeave, Lambda and Nebius.  These businesses are fairly straightforward. They own (or lease) data centers that they then fill full of servers that are full of NVIDIA GPUs, which they then rent on an hourly basis to customers, either on a per-GPU basis or in large batches for larger customers, who guarantee they'll use a certain amount of compute and sign up to long-term (i.e. more than an hour at a time) commitments. A neocloud is a specialist cloud compute company that exists only to provide access to GPUs for AI, unlike Amazon Web Services, Microsoft Azure and Google Cloud, all of which have healthy businesses selling other kinds of compute, with AI (as I’ll get into later) failing to provide much of a return on investment.  It’s not just the fact that these companies are more specialized than, say, Amazon’s AWS or Microsoft Azure. As you’ve gathered from the name, these are new, young, and in almost all cases, incredibly precarious businesses — each with financial circumstances that would make a Greek finance minister blush.  That’s because setting up a neocloud is expensive . Even if the company in question already has data centers — as CoreWeave did with its cryptocurrency mining operation — AI requires completely new data center infrastructure to house and cool the GPUs , and those GPUs also need paying for, and then there’s the other stuff I mentioned earlier, like power, water, and the other bits of the computer (the CPU, the motherboard, the memory and storage, and the housing).  As a result, these neoclouds are forced to raise billions of dollars in debt, which they collateralize using the GPUs they already have , along with contracts from customers, which they use to buy more GPUs. CoreWeave, for example, has $25 billion in debt on estimated revenues of $5.35 billion , losing hundreds of millions of dollars a quarter. You know who also invests in these neoclouds? NVIDIA! NVIDIA is also one of CoreWeave’s largest customers (accounting for 15% of its revenue in 2024), and just signed a deal to buy $6.3 billion of any capacity that CoreWeave can’t otherwise sell to someone else through 2032 , an extension of a $1.3 billion 2023 deal reported by the Information . It was the anchor investor ($250 million) in CoreWeave’s IPO , too. NVIDIA is currently doing the same thing with Lambda, another neocloud that NVIDIA invested in, which also  plans to go public next year. NVIDIA is also one of Lambda’s largest customers, signing a deal with it this summer to rent 10,000 GPUs for $1.3 billion over four years . In the UK, NVIDIA has just invested $700 million in Nscale , a former crypto miner that has never built an AI data center , and that has, despite having no experience, committed $1 billion (and/or 100,000 GPUs) to an OpenAI data center in Norway . On Thursday, September 25, Nscale announced it had closed another funding round, with NVIDIA listed as a main backer — although it’s unclear how much money it put in . It would be safe to assume it’s another few hundred million.  NVIDIA also invested in Nebius , an outgrowth of Russian conglomerate Yandex, and Nebius provides, through a partnership with NVIDIA, tens of thousands of dollars’ worth of compute credits to companies in NVIDIA’s Inception startup program. NVIDIA’s plan is simple: fund these neoclouds, let these neoclouds load themselves up with debt, at which point they buy GPUs from NVIDIA, which can then be used as collateral for loans, along with contracts from customers, allowing the neoclouds to buy even more GPUs. It’s like that Robinhood infinite money glitch… …except, that is, for one small problem. There don’t appear to be that many customers. As I went into recently on my premium newsletter , NVIDIA funds and sustains Neoclouds as a way of funnelling revenue to itself, as well as partners like Supermicro and Dell , resellers that take NVIDIA GPUs and put them in servers to sell pre-built to customers. These two companies made up 39% of NVIDIA’s revenues last quarter .  Yet when you remove hyperscaler revenue — Microsoft, Amazon, Google, OpenAI and NVIDIA — from the revenues of these neoclouds, there’s barely $1 billion in revenue combined, across CoreWeave, Nebius and Lambda . CoreWeave’s $5.35 billion revenue is predominantly made up of its contracts with NVIDIA, Microsoft (offering compute for OpenAI), Google ( hiring CoreWeave to offer compute for OpenAI ), and OpenAI itself, which has promised CoreWeave $22.4 billion in business over the next few years. This is all a lot of stuff , so I’ll make it really simple: there is no real money in offering AI compute, but that isn’t Jensen Huang’s problem, so he will simply force NVIDIA to hand money to these companies so that they have contracts to point to when they raise debt to buy more NVIDIA GPUs.  Neoclouds are effectively giant private equity vehicles that exist to raise money to buy GPUs from NVIDIA, or for hyperscalers to move money around so that they don’t increase their capital expenditures and can, as Microsoft did earlier in the year , simply walk away from deals they don’t like. Nebius’ “$17.4 billion deal” with Microsoft even included a clause in its 6-K filing that Microsoft can terminate the deal in the event the capacity isn’t built by the delivery dates, and Nebius has already used the contract to raise $3 billion to… build the data center to provide compute for the contract. Here, let me break down the numbers: From my analysis, it appears that CoreWeave, despite expectations to make that $5.35 billion this year, has only around $500 million of non-Magnificent Seven or OpenAI AI revenue in 2025 , with Lambda estimated to have around $100 million in AI revenue , and Nebius around $250 million without Microsoft’s share , and that’s being generous. In simpler terms, the Magnificent Seven is the AI bubble, and the AI bubble exists to buy more GPUs, because (as I’ll show) there’s no real money or growth coming out of this, other than in the amount that private credit is investing — “ $50 billion a quarter, for the low end, for the past three quarters .” I dunno man, let’s start simple: $50 billion a quarter of data center funding is going into an industry that has less revenue than Genshin Impact . That feels pretty bad. Who’s gonna use these data centers? How are they going to even make money on them? Private equity firms don’t typically hold onto assets, they sell them or take them public. Doesn’t seem great to me! Anyway, if AI was truly the next big growth vehicle, neoclouds would be swimming in diverse global revenue streams. Instead, they’re heavily-centralized around the same few names, one of which (NVIDIA) directly benefits from their existence not as a company doing business, but as an entity that can accrue debt and spend money on GPUs. These Neoclouds are entirely dependent on a continual flow of private credit from firms like Goldman Sachs ( Nebius , CoreWeave , Lambda for its IPO ), JPMorgan ( Lambda , Crusoe , CoreWeave ), and Blackstone ( Lambda , CoreWeave ), who have in a very real sense created an entire debt-based infrastructure to feed billions of dollars directly to NVIDIA, all in the name of an AI revolution that's yet to arrive. The fact that the rest of the neocloud revenue stream is effectively either a hyperscaler or OpenAI is also concerning. Hyperscalers are, at this point, the majority of data center capital expenditures , and have yet to prove any kind of success from building out this capacity, outside, of course, Microsoft’s investment in OpenAI, which has succeeded in generating revenue while burning billions of dollars .  Hyperscaler revenue is also capricious, but even if it isn’t, why are there no other major customers? Why, across all of these companies, does there not seem to be one major customer who isn’t OpenAI?  The answer is obvious: nobody that wants it can afford it, and those who can afford it don’t need it.  It’s also unclear what exactly hyperscalers are doing with this compute, because it sure isn’t “making money.” While Microsoft makes $10 billion in revenue from renting compute to OpenAI via Microsoft Azure, it does so at-cost, and was charging OpenAI $1.30-per-hour for each A100GPU it rents, a loss of $2.2 an hour per GPU , meaning that it is  likely losing money on this compute, especially as SemiAnalysis has the total cost per hour per GPU at around $1.46 with the cost of capital and debt associated for a hyperscaler, though it’s unclear if that’s for an H100 or A100 GPU. In any case, how do these neoclouds pay for their debt if the hyperscalers give up, or NVIDIA doesn’t send them money, or, more likely, private credit begins to notice that there’s no real revenue growth outside of circular compute deals with neoclouds’ largest supplier, investor and customer? They don’t! In fact, I have serious concerns that they can’t even build the capacity necessary to fulfil these deals, but nobody seems to worry about that. No, really! It appears to be taking Oracle and Crusoe around 2.5 years per gigawatt of compute capacity . How exactly are any of these neoclouds (or Oracle itself) able to expand to actually capture this revenue? Who knows! But I assume somebody is going to say “OpenAI!” Here’s an insane statistic for you: OpenAI will account for — in both its own revenue (projected $13 billion) and in its own compute costs ($16 billion, according to The Information, although that figure is likely out of date, and seemingly only includes the compute it’ll use, and not that it has committed to build, and thus has spent money on) — about 50% of all AI revenues in 2025. That figure takes into account the $400m ARR for ServiceNow, Adobe, and Salesforce ; the $35bn in revenue for the Magnificent Seven from AI (not profit, and based on figures from the previous year); revenue from neoclouds like CoreWeave, Nebius, and Lambda; and the estimated revenue from the entire generative AI industry (including Anthropic and other smaller players, like Perplexity and Anysphere) for a total of $55bn.OpenAI is the generative AI industry — and it’s a dog of a company. As a reminder, OpenAI has leaked that it’ll burn $115 billion in the next four years , and based on my estimates, it needs to raise more than $290 billion in the next four years based on its $300 billion deal with Oracle alone. That alone is a very, very bad sign, especially as we’re three years and $500 billion or more into this hype cycle with few signs of life outside of, well, OpenAI promising people money. Credit to Anthony Restaino for this horrifying graphic : This is not what a healthy, stable industry looks like. Alright, well, things can’t be that bad on the software side. As I covered on my premium newsletter a few weeks ago , everybody is losing money on generative AI, in part because the cost of running AI models is increasing , and in part because the software itself doesn’t do enough to warrant the costs associated with running them, which are already subsidized and unprofitable for the model providers .  Outside of OpenAI (and to a lesser extent Anthropic), nobody seems to be making much revenue, with the most “successful” company being Anysphere, makers of AI coding tool Cursor, which hit $500 million ‘annualized” ( so $41.6 million in one month ) a few months ago, just before Anthropic and OpenAI jacked up the prices for “priority processing” on enterprise queries , raising its operating costs as a result. In any case, that’s some piss-poor revenue for an industry that’s meant to be the future of software. Smartwatches are projected to make $32 billion this year , and as mentioned, the Magnificent Seven expects to make $35 billion or so in revenue from AI this year . Even Anthropic and OpenAI seem a little lethargic, both burning billions of dollars while making, by my estimates, no more than $2 billion and $6.26 billion in 2025 so far , despite projections of $5 billion and $13 billion respectively.  Outside of these two, AI startups are floundering, struggling to stay alive and raising money in several-hundred million dollar bursts as their negative-gross-margin businesses flounder.  As I dug into a few months ago , I could find only 12 AI-powered companies making more than $8.3 million a month, with two of them slightly improving their revenues, specifically AI search company Perplexity ( which has now hit $150 million ARR, or $12.5 million in a month ) and AI coding startup Replit ( which also hit $150 million ARR in September ).  Both of these companies burn ridiculous amounts of money. Perplexity burned 164% of its revenue on Amazon Web Services, OpenAI and Anthropic last year , and while Replit hasn’t leaked its costs, The Information reports its gross margins in July were 23% , which doesn’t include the costs of its free users, which you simply have to do with LLMs as free users are capable of costing you a hell of a lot of money. Problematically, your paid users can also cost you more than they bring in as well. In fact, every user loses you money in generative AI, because it’s impossible to do cost control in a consistent manner. A few months ago, I did a piece about Anthropic losing money on every single Claude Code subscriber , and I’ll walk you through it in a very simplified fashion: Anthropic is, to be clear, the second-largest model developer, and has some of the best AI talent in the industry. It has a better handle on its infrastructure than anyone outside of big tech and OpenAI. It still cannot seem to fix this problem, even with weekly rate limits . While one could assume that Anthropic is simply letting people run wild, my theory is far simpler: even the model developers have no real way of limiting user activity, likely due to the architecture of generative AI. I know it sounds insane, but at the most advanced level, model providers are still prompting their models, and whatever rate limits may be in place appear to, at times, get completely ignored, and there doesn’t seem to be anything they can do to stop it. No, really. Anthropic counts amongst its capitalist apex predators one lone Chinese man who spent $50,000 of their compute in the space of a month fucking around with Claude Code. Even if Anthropic was profitable — it isn’t, and will burn billions this year — a customer paying $200-a-month running up $50,000 in costs immediately devours the margin of any user running the service that day , if not that week or month. Even if Anthropic’s costs are half the published rates, one guy amounted to 125 users’ monthly revenue.  That’s not a real business! That’s a bad business with out-of-control costs, and it doesn’t appear anybody has these costs under control. A few weeks ago, Replit — an unprofitable AI coding company — released a product called “ Agent 3 .” which promised to be “10x more autonomous” and offer “infinitely more possibilities,” “[testing] and [fixing] its code, constantly improving your application behind the scenes in a reflection loop.” In reality, this means you’d go and tell the model to build something and it would “go do it,” and you’ll be shocked to hear that these models can’t be relied upon to “go and do” anything. Please note that this was launched a few months after Replit raised its prices, shifting to obfuscated “ effort-based ” pricing that would charge “the full scope of the agent’s work.” Agent 3 has been a disaster. Users found tasks that previously cost a few dollars were spiralling into the hundreds of dollars, with The Register reporting one customer found themselves with a $1000 bill after a week: Another user complained that “costs skyrocketed, without any concrete results”: As I previously reported, in late May/early June, both OpenAI and Anthropic cranked up the pricing on their enterprise customers , leading to Replit and Cursor both shifting their prices. This abuse has now trickled down to their customers. Replit has now released an update that lets you choose how autonomous you want Agent 3 to be , which is a tacit admission that you can’t trust coding LLMs to build software. Replit’s users are still pissed off, complaining that Replit is charging them for activity when the agent doesn’t do anything , a consistent problem across its Reddit. While Reddit is not the full summation of all users across every company, it’s a fairly good barometer of user sentiment, and man, are users pissy. Traditionally, Silicon Valley startups have relied upon the same model of “grow really fast and burn a bunch of money, then “turn the profit lever.” AI does not have a “profit lever,” because the raw costs of providing access to AI models are so high ( and they’re only increasing ) that the basic economics of how the tech industry sells software don’t make sense. I’ll reiterate something I wrote a few weeks ago : In simpler terms, it is very, very difficult to imagine what one user — free or otherwise — might cost, and thus it’s hard to charge them on a monthly basis, or tell them what a service might cost them on average. This is a huge problem with AI coding environments.  According to The Information , Claude Code was driving “nearly $400 million in annualized revenue, roughly doubling from a few weeks ago” on July 31 2025.  That annualized revenue works out to about $33 million a month in revenue for a company that predicts it will make at least $416 million a month by the end of the year, and for a product that has become the most-popular coding environment in the world, from the second-largest and best-funded AI company in the world. …is that it? Is that all that’s happening here?  $33 million dollars, all of it unprofitable, after it felt, at least based on social media chatter and discussing with multiple different software engineers, that Claude Code had become ubiquitous with anything to do with LLMs. To be clear, Anthropic’s Sonnet and Opus models are consistently some of the most popular for programming on Openrouter , an aggregator of LLM usage, and Anthropic has been consistently-named as “ the best at coding .”  Some bright spark out there is going to say that Microsoft’s Github Copilot has 1.8 million paying subscribers , and guess what, that’s true, and in fact, I reported it! Here’s another fun fact: the Wall Street Journal reported that Microsoft loses “on average more than $20-a-month-per-user,” with “...some users [costing] the company as much as $80.” And that’s for the most-popular product! If you believe the New York Times or other outlets that simply copy and paste whatever Dario Amodei says , you’d think that the reason that software engineers are having trouble finding work is because their jobs are being replaced by AI. This grotesque , abusive , manipulative and offensive lie has been propagated throughout the entire business and tech media without anybody sitting down and asking whether it’s true, or even getting a good understanding of what it is that LLMs can actually do with code. Members of the media, I am begging you, stop doing this. I get it, every asshole is willing to give a quote saying that “ coding is dead ,” and that every executive is willing to burp out some nonsense about replacing all of their engineers , but I am fucking begging you to either use these things yourself, or speak to people that do. I am not a coder. I cannot write or read code. Nevertheless, I am capable of learning , and have spoken to numerous software engineers in the last few months, and basically reached a consensus of “this is kind of useful, sometimes.” However, one very silly man once said that I don’t speak to people who use these tools , so I went and spoke to three notable, experienced software engineers, and asked them to give me the straight truth about what coding LLMs can do.  In simple terms, LLMs are capable of writing code , but can’t do software engineering, because software engineering is the process of understanding, maintaining and executing code to produce functional software, and LLMs do not “learn,” cannot “adapt,” and (to paraphrase Brown), break down the more of your code and variables you ask them to look at at once. It’s very easy to believe that software engineering is just writing code, but the reality is that software engineers maintain software , which includes writing and analyzing code among a vast array of different personalities and programs and problems . Good software engineering harkens back to Brian Merchant’s interviews with translators — while some may believe that translators simply tell you what words mean, true translation is communicating the meaning of a sentence , which is cultural, contextual, regional, and personal, and often requires the exercise of creativity and novel thinking.  My editor, Matthew Hughes, gave an example of this in his newsletter :  Similarly, coding is not just “a series of text that programs a computer,” but a series of interconnected characters that refers to other software in other places that must also function now and explain, on some level, to someone who has never, ever seen the code before, why it was done this way.  This is, by the way, why we are still yet to get any tangible proof that AI is replacing software engineers…because it can’t.  Of all the fields supposedly at risk from “AI disruption,” coding feels (or felt) the most tangible, if only because the answer to “can you write code with LLMs” wasn’t an immediate, unilateral no.  The media has also been quick to say that AI “writes software,” which is true in the same way that ChatGPT “writes novels”. In reality, LLMs can generate code, and do some software engineering-adjacent tasks, but, like all Large Language Models, break down and go totally insane, hallucinating more as the tasks get more complex . And, as I pointed out earlier, software engineering is not just coding. It involves thinking about problems, finding solutions to novel challenges, designing stuff in a way that can be read and maintained by others, and that’s (ideally) scalable and secure. The whole fucking point of an “AI” is that you hand shit off to it! That’s what they’ve been selling it as! That’s why Jensen Huang told kids to stop learning to code, as with AI, there’s no point .  And it was all a lie. Generative AI can’t do the job of a software engineer, and it fails while  also costing abominable amounts of money.  Coding LLMs seem like magic at first, because they (to quote a conversation with Carl Brown) make the easy things easier, but they also make the harder things harder. They don’t even speed up engineers — they actually make them slower ! Yet coding is basically the only obvious use case for LLMs.  I’m sure you’re gonna say “but I bet the enterprise is doing well!” and you are so very, very wrong. Before I go any further, let’s establish some facts: All of this is to say that Microsoft has one of the largest commercial software empires in history, thousands (if not tens of thousands) of salespeople, and thousands of companies that literally sell Microsoft services for a living . And it can’t sell AI. A source that has seen materials related to sales has confirmed that, as of August 2025, Microsoft has around eight million active licensed users of Microsoft 365 Copilot, amounting to a 1.81% conversion rate across the 440 million Microsoft 365 subscribers. This would amount to, if each of these users paid annually at the full rate of $30-a-month, to about $2.88 billion in annual revenue for a product category that makes $33 billion a fucking quarter. And I must be clear, I am 100% sure these users aren’t all paying $30 a month. The Information reported a few weeks ago that Microsoft has been “reducing the software’s price with more generous discounts on the AI features, according to customers and salespeople,” heavily suggesting discounts had already been happening. Enterprise software is traditionally sold at a discount anyway — or, put a different way, with bulk pricing for those who sign up a bunch of users at once.  In fact, I’ve found evidence that it’s been doing this a while, with a 15% discount on annual Microsoft 365 Copilot subscriptions for orders of 10-to-300 seats mentioned by an IT consultant back in late 2024 , and another that’s currently running through September 30, 2025 through Microsoft’s Cloud Solution Provider program , with up to 2400 licenses discounted if you pay upfront for the year. Microsoft seems to do this a lot, as I found another example of an offer that ran from January 1 2025 through March 31 2025 . An “active” user is someone who has taken one action on Copilot in any Microsoft 365 app in the space of 28 days. Now, I know. That word, active. Maybe you’re thinking “Ed, this is like the gym model! There are unpaid licenses that Microsoft is getting paid for!”  Fine! Let’s assume that Microsoft also has, based on research that suggests this is the case for all software companies, another 50% — four million — of paid Copilot licenses that aren’t being used. That still makes this 12 million users, which is still a putrid 2.72% conversion rate. So, why aren’t people paying for Copilot? Let’s hear from someone who talked to The Information : Microsoft 365 Copilot has been such a disaster that Microsoft will now integrate Anthropic’s models in an attempt and make them better.  Oh, one other thing: sources also confirm GPU utilization for Microsoft 365’s enterprise Copilot is barely scratching 60%.  I’m also hearing that less than SharePoint — another popular enterprise app from Microsoft with 250 million users — had less than 300,000 weekly active users of its AI copilot features in August. So, The Information reported a few months ago that Microsoft’s projected AI revenues would be $13 billion, with $10 billion of that from OpenAI, leaving about $3 billion of total revenue across Microsoft 365 Copilot and any other foreseeable feature that Microsoft sells with “AI” on it. This heavily suggests that Microsoft is making somewhere between $1.5 billion and $2 billion on Azure or Microsoft 365 Copilot, though I suppose there are other places it could be making AI revenue too. Right? I guess. In any case, Microsoft’s net income (read: profit) in its last quarterly earnings was $27.2 billion. One of the comfortable lies that people tell themselves is that the AI bubble is similar to the fiber boom, or the dot com bubble, or Uber, or that we’re in the “growth stage,” or that “this is what software companies do, they spend a bunch of money then “ pull the profit lever .”  This is nothing like anything you’ve seen before, because this is the dumbest shit that the tech industry has ever done.  AI data centers are nothing like fiber, because there are very few actual use cases for these GPUs outside of AI, and none of them are remotely hyperscale revenue drivers. As I discussed a month or so ago , data center development accounted for more of America’s GDP growth than all consumer spending combined, and there really isn’t any demand for AI in general, let alone at the scale that these hundreds of billions of dollars are being sunk into.  The conservative estimate of capital expenditures related to data centers is around $400 billion, but given the $50 billion a quarter in private credit, I’m going to guess it breaks $500 billion, all to build capacity for an industry yet to prove itself. And this NVIDIA-OpenAI “$100 billion funding” news should only fill you full of dread, but also it isn’t fucking finalized, stop reporting it as if it’s done, I swear to god- Anyway, according to CNBC , “the initial $10 billion tranche is locked in at a $500 billion valuation and expected to close within a month or so once the transaction has been finalized,” with “successive $10 billion rounds are planned, each to be priced at the company’s then-current valuation as new capacity comes online.”  At no point is anyone asking how, exactly, OpenAI builds data centers to fill full of these GPUs. In fact, I am genuinely shocked (and a little disgusted!) by how poorly this story has been told. Let’s go point by point: To be clear, when I say OpenAI needs at least $300 billion over the next four years, that’s if you believe its projections, which you shouldn’t .  Let’s walk through its (alleged) numbers, while plagiarizing myself :  According to The Information , here's the breakdown (these are projections): OpenAI's current reported burn is $116 billion through 2030, which means there is no way that these projections include $300 billion in compute costs, even when you factor in revenue. There is simply no space in these projections to absorb that $300 billion, and from what I can tell, by 2029, OpenAI will have actually burned more than $290 billion, assuming that it survives that long, which I do not believe it will. Don’t worry, though. OpenAI is about to make some crazy money . Here are the projections that CFO Sarah Friar signed off on : Just so we are clear, OpenAI intends to 10x its revenue in the space of four years, selling software and access to models in an industry with about $60 billion of revenue in 2025. How will it do this? It doesn’t say. I don’t know OpenAI CFO Sarah Friar, but I do know that signing off on these numbers is, at the very least, ethically questionable.  Putting aside the ridiculousness of OpenAI’s deals, or its funding requirements, Friar has willfully allowed Sam Altman and OpenAI to state goals that defy reality or good sense, all to take advantage of investors and public markets that have completely lost the plot.  I need to be blunter: OpenAI has signed multiple different deals and contracts for amounts it cannot afford to pay, that it cannot hope to raise the money to pay for, that defy the amounts of venture capital and private credit available, all to sustain a company that will burn $300 billion and has no path to profitability of any kind. So, as I said above, CNBC reported on September 23, 2025 that the NVIDIA deal will be delivered in $10 billion tranches, the first of which is “expected to close within a month,” and the rest delivered “as new capacity comes online.” This is, apparently, all part of a plan to build 10GW of data center capacity with NVIDIA. A few key points: So, let’s start simple: data centers take forever to build. As I said previously, based on current reports, it’s taking Oracle and Crusoe around 2.5 years per gigawatt of data center capacity, and nowhere in these reports does one reporter take a second to say “hey, what data centers are you talking about?” or “hey, didn’t Sam Altman say back in July that he was building 10GW of data center capacity with Oracle? ” But wait, now Oracle and OpenAI have done another announcement that says they’re only doing 7GW, but they’re “ahead of schedule” on 10GW?  Wait, is NVIDIA’s 10GW the same 10GW as Oracle and OpenAI are working on? Is it different? Nobody seems to know or care! Anyway, I cannot be clear enough how unlikely it is that (as NVIDIA has said) “ the first gigawatt of NVIDIA systems will be deployed in the second half of 2026 ,” and that’s if it has bought the land and got the permits and ordered the construction, none of which has happened yet. But let’s get really specific on costs!  Crusoe’s 1.2GW of compute for OpenAI is a $15 billion joint venture , which means a gigawatt of compute runs about $12.5 billion. Abilene’s eight buildings are meant to hold 50,000 NVIDIA GB200 GPUs and their associated networking infrastructure, so let’s say a gigawatt is around 333,333 Blackwell GPUs. Though this math is a little funky due to NVIDIA promising to install its new Rubin GPUs in these theoretical data centers, that means these data centers will require a little under $200 billion worth of GPUs. By my maths that’s $325 billion.  I’m so tired of this. A number of you have sent me the following image with some sort of comment about how “this is how it’ll work,” and you are wrong, because this is neither how it works nor how it will work nor accurate on any level. In the current relationship, NVIDIA Is Not Sending OpenAI $100 Billion, nor will it send it that much money, because 90% of OpenAI’s funding is gated behind building 9 or 10 gigawatts of data center capacity. In the current relationship, OpenAI does not have the money to pay Oracle. Also, can Oracle even afford to give that much money to NVIDIA? It had negative free cash flow last quarter , already has $104 billion in debt , and its biggest new customer cannot afford a single fucking thing it’s promised. The only company in this diagram that actually can afford to do any of this shit is NVIDIA, and even then it only has $56 billion cash on hand . In any case, as I went over on Friday, OpenAI has promised about a trillion dollars between compute contracts across Oracle, Microsoft, Google and CoreWeave, 17 Gigawatts of promised data centers in America between NVIDIA and “Stargate,” several more gigawatts of international data centers, custom chips from Broadcom, and their own company operations. How exactly does this get paid for?  Nobody seems to ask these questions! Why am I the asshole doing this? Don’t we have tech analysts that are meant to analyse shit? AHhhhh- Every time I sit down to write about this subject the newsletters seem to get longer, because people are so painfully attached to the norms and tropes of the past. This post is, already, 17,500 words — a record for this newsletter — and I’ve still not finished editing and expanding it.  What we’re witnessing is one of the most egregious wastes of capital in history, sold by career charlatans with their reputations laundered by a tech and business media afraid to criticize the powerful and analysts that don’t seem to want to tell their investors the truth. There are no historic comparisons here — even Britain’s abominable 1800s railway bubble, which absorbed half of the country’s national income , created valuable infrastructure for trains, a vehicle that can move people to and from places. GPUs are not trains, nor are they cars, or even CPUs. They are not adaptable to many other kinds of work, nor are they “the infrastructure of the future of tech,” because they’re already quite old and with everybody focused on buying them, you’d absolutely see one other use case by now that actually mattered. GPUs are expensive, power-hungry, environmentally destructive and require their own kinds of cooling and server infrastructure, making every GPU data center and environmental and fiscal bubble unto themselves. And, whereas the Victorian train infrastructure still exists in the UK — though it has been upgraded over the years — a GPU has a limited useful lifespan. These are cards that can — and will — break after a period of extended usage, whether that period is five years or later, and they’ll inevitably be superseded by something better and more powerful, meaning that the resale value of that GPU will only go down, with a price depreciation that’s akin to a new car.  I am telling you, as I have been telling you for years, again and again and again , that the demand is not there for generative AI, and the demand is never, ever arriving. The only reason anyone humours any of this crap is the endless hoarding of GPUs to build capacity for a revolution that will never arrive. Well, that and OpenAI, a company built and sold on lies about ChatGPT’s capabilities . ChatGPT’s popularity — and OpenAI’s hunger for endless amounts of compute — have created the illusion of demand due to the sheer amount of capacity required to keep their services operational, all so they can burn $8 billion or more in 2025 and, if my estimates are right, nearly a trillion dollars by 2030 . This NVIDIA deal is a farce — an obvious attempt by the largest company on the American stock market to prop up the one significant revenue-generator in the entire industry, knowing that time is running out for it to create new avenues for eternal growth. I’d argue that NVIDIA’s deal also shows the complete contempt that these companies have for the media. There are no details about how this deal works beyond the initial $10 billion, there’s no land purchased, no data center construction started, and yet the media slurps it down without a second thought. I am but one man, and I am fucking peculiar. I did not learn financial analysis in school, but I appear to be one of the few people doing even the most basic analysis of these deals, and while I’m having a great time doing so, I am also exceedingly frustrated at how little effort is being put into prying apart these deals. I realize how ridiculous all of this sounds. I get it. There’s so much money being promised to so many people, market rallies built off the back of massive deals , and I get that the assumption is that this much money can’t be wrong, that this many people wouldn’t just say stuff without intending to follow through, or without considering whether their company could afford it.  I know it’s hard to conceive that hundreds of billions of dollars could be invested in something for no apparent reason, but it’s happening, right god damn now, in front of your eyes, and I am going to be merciless on anyone who attempts to write a “how could we see this coming?”  Generative AI has never been reliable, has always been unprofitable, and has always been unsustainable, and I’ve been saying so since February 2024 . The economics have never made sense, something I’ve said repeatedly since April 2024 , and when I wrote “How Does OpenAI Survive?” in July 2024 , I had multiple people suggest I was being alarmist. Here’s some alarmism for you: the longer it takes for OpenAI to die, the more damage it will cause to the tech industry.  On Friday, when I put out my piece on OpenAI needing a trillion dollars , I asked analyst Gil Luria if the capital was there to build the 17 Gigawatts that OpenAI had allegedly planned to build. He said the following: That doesn’t sound good! Anyway, as I discussed earlier, venture capital could run out in six quarters, with investor and researcher Jon Sakoda estimating that there will only be around $164 billion of dry powder (available capital) in US VC firms by the end of 2025. In July, The French Tech Journal reported (using Pitchbook data) that global venture capital deal activity reached its lowest first-half total since 2018, with $139.4 billion in deal value in the first half of 2025, down from $183.4 billion in the first half of 2024, meaning that any further expansion or demands for venture capital from OpenAI will likely sap the dwindling funds available from other startups. Things get worse when you narrow things to US venture capital. In a piece from April , EY reported that VC-backed investment in US companies hit $80 billion in Q1 2025, but “one $40 billion deal” accounted for half of the investment — OpenAI’s $40 billion deal of which only $10 billion has actually closed, and that didn’t happen until fucking June . Without the imaginary money from OpenAI, US venture would have declined by 36%. The longer that OpenAI survives, the longer it will sap the remaining billions from the tech ecosystem, and I expect it to extend its tendrils to private credit too. The $325 billion it needs just to fulfil its NVIDIA contract, albeit over 4 years, is an egregious sum that I believe exceeds the available private capital in the world. Let’s get specific, and check out the top 10 private equity firms’ available capital!  Assuming that all of this capital is currently available, the top 10 private equity firms in the world have around $477 billion of available capital. We can, of course, include investment banks — Goldman Sachs had around $520 billion cash in hand available at the end of its last quarter , and JPMorgan over $1.7 trillion , but JP Morgan has only dedicated $50 billion in direct lending commitments as of February 2025 , and while Goldman Sachs expanded its direct private credit lending by $15 billion back in June , that appears to be an extension of its “more than $20 billion” direct lending close from mid-2024 . Include both of those, and that brings us up to — if we assume that all of these funds are available — $562 billion in capital and about $164 billion in US venture available to spend, and that’s meant to go to more places than just OpenAI. Sure, sure, there’s more than just the top 10 private equity firms and there’s venture money outside of the US, but what could it be? Like, another $150 billion? You see, OpenAI needs to buy those GPUs, and it needs to build those data centers, and it needs to pay its thousands of staff and marketing and sales costs too. While OpenAI likely wouldn’t be the ones raising the money for the data centers — and honestly, I’m not sure who would do it at this point? — somebody is going to need to build TWENTY GIGAWATTS OF DATA CENTERS if we’re to believe both Oracle and NVIDIA You may argue that venture funds and private credit can raise more, and you’re right! But at this point, there have been few meaningful acquisitions of AI companies, and zero exits from the billions of dollars put into data centers.  Even OpenAI admits in its own announcement about new Stargate sites that this will be a “$400 billion investment over 3 years.” Where the fuck is that money coming from? Is OpenAI really going to absorb massive chunks of all available private credit and venture capital for the next few years?  And no, god, stop saying the US government will bail this out. It will have to bail out hundreds of billions of dollars, there is no scenario where it’s anything less than that, and I’ve already been over this. While the US government has spent equivalent sums in the past to support private business (the total $440 billion dispersed during the Great Recession’s TARP program, where the Treasury bought toxic assets from investment banks to stop them from imploding a la Lehman, springs to mind), it’s hard to imagine any case where OpenAI is seen as vital to the global financial system — and the economic health of the US — as the banking system.  Sure, we spent around $1tn — if we’re being specific, $953bn — on the Paycheck Protection Program during the Covid era, but that was to keep people employed at a time when the economy outside of Zoom and Walmart had, for all intents and purposes, ceased to exist. There was an urgency that doesn’t apply here. If OpenAI goes tits up, Softbank loses some money — nothing new there — and Satya Nadella has to explain why he spent tens of billions of dollars on a bunch of data centers filled with $50,000 GPUs that are, at this point, ornamental.  And while there will be — and have been — disastrous economic consequences, they won’t be as systemically catastrophic as that of the pandemic, or the global financial crisis. To be clear, it’ll be bad, but not as bad .   And there’s also the problem of moral hazard — if the government steps in, what’s to stop big tech chasing its next fruitless rainbow? — and optics. If people resented bailing out the banks after they acted like profligate gamblers and lost, how will they feel bailing out f ucking Sam Altman and Jensen Huang ?  I do apologize for the length of this piece, but the significance of this bubble requires depth. There is little demand, little real money, and little reason to continue, and the sheer lack of responsibility and willingness to kneel before the powerful fills me full of angry bile. I understand many journalists are not in a position where they can just write “this shit sounds stupid,” but we have entered a deeply stupid era, and by continuing to perpetuate the myth of AI, the media guarantees that retail investors and regular people’s 401Ks will suffer. It is now inevitable that this bubble bursts. Deutsche Bank has said the AI boom is unsustainable outside of tech spending “remaining parabolic,” which it says “is highly unlikely,” and Bain Capital has said that $2 trillion in new revenue is needed to fund AI’s scaling , and even that math is completely fucked as it talks about “AI-related savings”: Even when stared in the face by a ridiculous idea — $2 trillion of new revenue in a global software market that’s expected to be around $817 billion in 2025 — Bain still oinks out some nonsense about the “savings from applying AI in sales, marketing, customer support and R&D,” yet another myth perpetuated I assume to placate the fucking morons sinking billions into this. Every single “vibe coding is the future,” “the power of AI,” and “AI job loss” story written perpetuates a myth that will only lead to more regular people getting hurt when the bubble bursts. Every article written about OpenAI or NVIDIA or Oracle that doesn’t explicitly state that the money doesn’t exist, that the revenues are impossible, that one of the companies involved burns billions of dollars and has no path to profitability, is an act of irresponsible make believe and mythos. I am nobody. I am not a financier. I am not anybody special. I just write a lot, and read a lot, and can do the most basic maths in the world. I am not trying to be anything other than myself, nor do I have an agenda, other than the fact that I like doing this and I hate how this story is being told. I never planned for this newsletter to get this big, and now that it has, I’m going to keep doing the same thing every week. I also believe that the way to stop this happening again is to have a thorough and well-sourced explanation of everything as it happens, ripping down the narratives as they’re spun and making it clear who benefits from them and how and why they’re choosing to do so. When things collapse, we need to be clear about how many times people chose to look the other way, or to find good faith ways to interpret bad faith announcements and leak. So, how could we have seen this coming? I don’t know. Did anybody try to fucking look?

0 views
Armin Ronacher 2 weeks ago

90%

“I think we will be there in three to six months, where AI is writing 90% of the code. And then, in 12 months, we may be in a world where AI is writing essentially all of the code” — Dario Amodei Three months ago I said that AI changes everything. I came to that after plenty of skepticism. There are still good reasons to doubt that AI will write all code, but my current reality is close. For the infrastructure component I started at my new company, I’m probably north of 90% AI-written code. I don’t want to convince you — just share what I learned. In parts, because I approached this project differently from my first experiments with AI-assisted coding. The service is written in Go with few dependencies and an OpenAPI-compatible REST API. At its core, it sends and receives emails. I also generated SDKs for Python and TypeScript with a custom SDK generator. In total: about 40,000 lines, including Go, YAML, Pulumi, and some custom SDK glue. I set a high bar, especially that I can operate it reliably. I’ve run similar systems before and knew what I wanted. Some startups are already near 100% AI-generated. I know, because many build in the open and you can see their code. Whether that works long-term remains to be seen. I still treat every line as my responsibility, judged as if I wrote it myself. AI doesn’t change that. There are no weird files that shouldn’t belong there, no duplicate implementations, and no emojis all over the place. The comments still follow the style I want and, crucially, often aren’t there. I pay close attention to the fundamentals of system architecture, code layout, and database interaction. I’m incredibly opinionated. As a result, there are certain things I don’t let the AI do. I know it won’t reach the point where I could sign off on a commit. That’s why it’s not 100%. As contrast: another quick prototype we built is a mess of unclear database tgables, markdown file clutter in the repo, and boatloads of unwanted emojis. It served its purpose — validate an idea — but wasn’t built to last, and we had no expectation to that end. I began in the traditional way: system design, schema, architecture. At this state I don’t let the AI write, but I loop it in AI as a kind of rubber duck. The back-and-forth helps me see mistakes, even if I don’t need or trust the answers. I did get the foundation wrong once. I initially argued myself into a more complex setup than I wanted. That’s a part where I later used the LLM to redo a larger part early and clean it up. For AI-generated or AI-supported code, I now end up with a stack that looks something like something I often wanted, but was too hard to do by hand: Raw SQL: This is probably the biggest change to how I used to write code. I really like using an ORM, but I don’t like some of its effects. In particular, once you approach the ORM’s limits, you’re forced to switch to handwritten SQL. That mapping is often tedious because you lose some of the powers the ORM gives you. Another consequence is that it’s very hard to find the underlying queries, which makes debugging harder. Seeing the actual SQL in your code and in the database log is powerful. You always lose that with an ORM. The fact that I no longer have to write SQL because the AI does it for me is a game changer. I also use raw SQL for migrations now. OpenAPI first: I tried various approaches here. There are many frameworks you can use. I ended up first generating the OpenAPI specification and then using code generation from there to the interface layer. This approach works better with AI-generated code. The OpenAPI specification is now the canonical one that both clients and server shim is based on. Today I use Claude Code and Codex. Each has strengths, but the constant is Codex for code review after PRs. It’s very good at that. Claude is indispensable still when debugging and needing a lot of tool access (eg: why do I have a deadlock, why is there corrupted data in the database etc.). The working together of the two is where it’s most magical. Claude might find the data, Codex might understand it better. I cannot stress enough how bad the code from these agents can be if you’re not careful. While they understand system architecture and how to build something, they can’t keep the whole picture in scope. They will recreate things that already exist. They create abstractions that are completely inappropriate for the scale of the problem. You constantly need to learn how to bring the right information to the context. For me, this means pointing the AI to existing implementations and giving it very specific instructions on how to follow along. I generally create PR-sized chunks that I can review. There are two paths to this: Agent loop with finishing touches: Prompt until the result is close, then clean up. Lockstep loop: Earlier I went edit by edit. Now I lean on the first method most of the time, keeping a todo list for cleanups before merge. It requires intuition to know when each approach is more likely to lead to the right results. Familiarity with the agent also helps understanding when a task will not go anywhere, avoiding wasted cycles. The most important piece of working with an agent is the same as regular software engineering. You need to understand your state machines, how the system behaves at any point in time, your database. It is easy to create systems that appear to behave correctly but have unclear runtime behavior when relying on agents. For instance, the AI doesn’t fully comprehend threading or goroutines. If you don’t keep the bad decisions at bay early it, you won’t be able to operate it in a stable manner later. Here’s an example: I asked it to build a rate limiter. It “worked” but lacked jitter and used poor storage decisions. Easy to fix if you know rate limiters, dangerous if you don’t. Agents also operate on conventional wisdom from the internet and in tern do things I would never do myself. It loves to use dependencies (particularly outdated ones). It loves to swallow errors and take away all tracebacks. I’d rather uphold strong invariants and let code crash loudly when they fail, than hide problems. If you don’t fight this, you end up with opaque, unobservable systems. For me, this has reached the point where I can’t imagine working any other way. Yes, I could probably have done it without AI. But I would have built a different system in parts because I would have made different trade-offs. This way of working unlocks paths I’d normally skip or defer. Here are some of the things I enjoyed a lot on this project: Research + code, instead of research and code later: Some things that would have taken me a day or two to figure out now take 10 to 15 minutes. It allows me to directly play with one or two implementations of a problem. It moves me from abstract contemplation to hands on evaluation. Trying out things: I tried three different OpenAPI implementations and approaches in a day. Constant refactoring: The code looks more organized than it would otherwise have been because the cost of refactoring is quite low. You need to know what you do, but if set up well, refactoring becomes easy. Infrastructure: Claude got me through AWS and Pulumi. Work I generally dislike became a few days instead of weeks. It also debugged the setup issues as it was going through them. I barely had to read the docs. Adopting new patterns: While they suck at writing tests, they turned out great at setting up test infrastructure I didn’t know I needed. I got a recommendation on Twitter to use testcontainers for testing against Postgres. The approach runs migrations once and then creates database clones per test. That turns out to be super useful. It would have been quite an involved project to migrate to. Claude did it in an hour for all tests. SQL quality: It writes solid SQL I could never remember. I just need to review which I can. But to this day I suck at remembering and when writing it. Is 90% of code going to be written by AI? I don’t know. What I do know is, that for me, on this project, the answer is already yes. I’m part of that growing subset of developers who are building real systems this way. At the same time, for me, AI doesn’t own the code. I still review every line, shape the architecture, and carry the responsibility for how it runs in production. But the sheer volume of what I now let an agent generate would have been unthinkable even six months ago. That’s why I’m convinced this isn’t some far-off prediction. It’s already here — just unevenly distributed — and the number of developers working like this is only going to grow. That said, none of this removes the need to actually be a good engineer. If you let the AI take over without judgment, you’ll end up with brittle systems and painful surprises (data loss, security holes, unscalable software). The tools are powerful, but they don’t absolve you of responsibility. Raw SQL: This is probably the biggest change to how I used to write code. I really like using an ORM, but I don’t like some of its effects. In particular, once you approach the ORM’s limits, you’re forced to switch to handwritten SQL. That mapping is often tedious because you lose some of the powers the ORM gives you. Another consequence is that it’s very hard to find the underlying queries, which makes debugging harder. Seeing the actual SQL in your code and in the database log is powerful. You always lose that with an ORM. The fact that I no longer have to write SQL because the AI does it for me is a game changer. I also use raw SQL for migrations now. OpenAPI first: I tried various approaches here. There are many frameworks you can use. I ended up first generating the OpenAPI specification and then using code generation from there to the interface layer. This approach works better with AI-generated code. The OpenAPI specification is now the canonical one that both clients and server shim is based on. Agent loop with finishing touches: Prompt until the result is close, then clean up. Lockstep loop: Earlier I went edit by edit. Now I lean on the first method most of the time, keeping a todo list for cleanups before merge. Research + code, instead of research and code later: Some things that would have taken me a day or two to figure out now take 10 to 15 minutes. It allows me to directly play with one or two implementations of a problem. It moves me from abstract contemplation to hands on evaluation. Trying out things: I tried three different OpenAPI implementations and approaches in a day. Constant refactoring: The code looks more organized than it would otherwise have been because the cost of refactoring is quite low. You need to know what you do, but if set up well, refactoring becomes easy. Infrastructure: Claude got me through AWS and Pulumi. Work I generally dislike became a few days instead of weeks. It also debugged the setup issues as it was going through them. I barely had to read the docs. Adopting new patterns: While they suck at writing tests, they turned out great at setting up test infrastructure I didn’t know I needed. I got a recommendation on Twitter to use testcontainers for testing against Postgres. The approach runs migrations once and then creates database clones per test. That turns out to be super useful. It would have been quite an involved project to migrate to. Claude did it in an hour for all tests. SQL quality: It writes solid SQL I could never remember. I just need to review which I can. But to this day I suck at remembering and when writing it.

0 views
Anton Zhiyanov 2 weeks ago

Go proposal: Hashers

Part of the Accepted! series, explaining the upcoming Go changes in simple terms. Provide a consistent approach to hashing and equality checks in custom data structures. Ver. 1.26 • Stdlib • Medium impact The new interface is the standard way to hash and compare elements in custom collections: The type is the default hasher implementation for comparable types, like numbers, strings, and structs with comparable fields. The package offers hash functions for byte slices and strings, but it doesn't provide any guidance on how to create custom hash-based data structures. The proposal aims to improve this by introducing hasher — a standardized interface for hashing and comparing the members of a collection, along with a default implementation. Add the hasher interface to the package: Along with the default hasher implementation for comparable types: Here's a case-insensitive string hasher: And a generic that uses a pluggable hasher for custom equality and hashing: The helper method uses the hasher to compute the hash of a value: This hash is used in the and methods. It acts as a key in the bucket map to find the right bucket for a value. checks if the value exists in the corresponding bucket: adds a value to the corresponding bucket: Now we can create a case-insensitive string set: Or a regular string set using : 𝗣 70471 • 𝗖𝗟 657296 (in progress)

2 views
Sean Goedecke 2 weeks ago

What is "good taste" in software engineering?

Technical taste is different from technical skill. You can be technically strong but have bad taste, or technically weak with good taste. Like taste in general, technical taste sometimes runs ahead of your ability: just like you can tell good food from bad without being able to cook, you can know what kind of software you like before you’ve got the ability to build it. You can develop technical ability by study and repetition, but good taste is developed in a more mysterious way. Here are some indicators of software taste: I think taste is the ability to adopt the set of engineering values that fit your current project . Aren’t the indicators above just a part of skill? For instance, doesn’t code look good if it’s good code ? I don’t think so. Let’s take an example. Personally, I feel like code that uses map and filter looks nicer than using a for loop. It’s tempting to think that this is a case of me being straightforwardly correct about a point of engineering. For instance, map and filter typically involve pure functions, which are easier to reason about, and they avoid an entire class of off-by-one iterator bugs. It feels to me like this isn’t a matter of taste, but a case where I’m right and other engineers are wrong. But of course it’s more complicated than that. Languages like Golang don’t contain map and filter at all, for principled reasons. Iterating with a for loop is easier to reason about from a performance perspective, and is more straightforward to extend to other iteration strategies (like taking two items at a time). I don’t care about these reasons as much as I care about the reasons in favour of map and filter - that’s why I don’t write a lot of for loops - but it would be far too arrogant for me to say that engineers who prefer for loops are simply less skilled. In many cases, they have technical capabilites that I don’t have. They just care about different things. In other words, our disagreement comes down to a difference in values . I wrote about this point in I don’t know how to build software and you don’t either . Even if the big technical debates do have definite answers, no working software engineer is ever in a position to know what those answers are, because you can only fit so much experience into one career. We are all at least partly relying on our own personal experience: on our particular set of engineering values. Almost every decision in software engineering is a tradeoff. You’re rarely picking between two options where one is strictly better. Instead, each option has its own benefits and downsides. Often you have to make hard tradeoffs between engineering values : past a certain point, you cannot easily increase performance without harming readability, for instance 1 . Really understanding this point is (in my view) the biggest indicator of maturity in software engineering. Immature engineers are rigid about their decisions. They think it’s always better to do X or Y. Mature engineers are usually willing to consider both sides of a decision, because they know that both sides come with different benefits. The trick is not deciding if technology X is better than Y, but whether the benefits of X outweigh Y in this particular case . In other words, immature engineers are too inflexible about their taste . They know what they like, but they mistake that liking for a principled engineering position. What defines a particular engineer’s taste? In my view, your engineering taste is composed of the set of engineering values you find most important . For instance: Resiliency . If an infrastructure component fails (a service dies, a network connection becomes unavailable), does the system remain functional? Can it recover without human intervention? Speed . How fast is the software, compared to the theoretical limit? Is work being done in the hot path that isn’t strictly necessary? Readability . Is the software easy to take in at a glance and to onboard new engineers to? Are functions relatively short and named well? Is the system well-documented? Correctness . Is it possible to represent an invalid state in the system? How locked-down is the system with tests, types, and asserts? Do the tests use techniques like fuzzing? In the extreme case, has the program been proven correct by formal methods like Alloy ? Flexibility . Can the system be trivially extended? How easy is it to make a change? If I need to change something, how many different parts of the program do I need to touch in order to do so? Portability . Is the system tied down to a particular operational environment (say, Microsoft Windows, or AWS)? If the system needs to be redeployed elsewhere, can that happen without a lot of engineering work? Scalability . If traffic goes up 10x, will the system fall over? What about 100x? Does the system have to be over-provisioned or can it scale automatically? What bottlenecks will require engineering intervention? Development speed . If I need to extend the system, how fast can it be done? Can most engineers work on it, or does it require a domain expert? There are many other engineering values: elegance, modern-ness, use of open source, monetary cost of keeping the system running, and so on. All of these are important, but no engineer cares equally about all of these things. Your taste is determined by which of these values you rank highest. For instance, if you value speed and correctness more than development speed, you are likely to prefer Rust over Python. If you value scalability over portability, you are likely to argue for a heavy investment in your host’s (e.g. AWS) particular quirks and tooling. If you value resiliency over speed, you are likely to want to split your traffic between different regions. And so on 2 . It’s possible to break these values down in a more fine-grained way. Two engineers who both deeply care about readability could disagree because one values short functions and the other values short call-stacks. Two engineers who both care about correctness could disagree because one values exhaustive test suites and the other values formal methods. But the principle is the same - there are lots of possible engineering values to care about, and because they are often in tension, each engineer is forced to take some more seriously than others. I’ve said that all of these values are important. Despite that, it’s possible to have bad taste. In the context of software engineering, bad taste means that your preferred values are not a good fit for the project you’re working on . Most of us have worked with engineers like this. They come onto your project evangelizing about something - formal methods, rewriting in Golang, Ruby meta-programming, cross-region deployment, or whatever - because it’s worked well for them in the past. Whether it’s a good fit for your project or not, they’re going to argue for it, because it’s what they like. Before you know it, you’re making sure your internal metrics dashboard has five nines of reliability, at the cost of making it impossible for any junior engineer to understand. In other words, most bad taste comes from inflexibility . I will always distrust engineers who justify decisions by saying “it’s best practice”. No engineering decision is “best practice” in all contexts! You have to make the right decision for the specific problem you’re facing. One interesting consequence of this is that engineers with bad taste are like broken compasses. If you’re in the right spot, a broken compass will still point north. It’s only when you start moving around that the broken compass will steer you wrong. Likewise, many engineers with bad taste can be quite effective in the particular niche where their preferences line up with what the project needs. But when they’re moved between projects or jobs, or when the nature of the project changes, the wheels immediately come off. No job stays the same for long, particularly in these troubled post-2021 times . Good taste is a lot more elusive than technical ability. That’s because, unlike technical ability, good taste is the ability to select the right set of engineering values for the particular technical problem you’re facing . It’s thus much harder to identify if someone has good taste: you can’t test it with toy problems, or by asking about technical facts. You need there to be a real problem, with all of its messy real-world context. You can tell you have good taste if the projects you’re working on succeed. If you’re not meaningfully contributing to the design of a project (maybe you’re just doing ticket-work), you can tell you have good taste if the projects where you agree with the design decisions succeed, and the projects where you disagree are rocky. Importantly, you need a set of different kinds of projects. If it’s just the one project, or the same kind of project over again, you might just be a good fit for that. Even if you go through many different kinds of projects, that’s no guarantee that you have good taste in domains you’re less familiar with 3 . How do you develop good taste? It’s hard to say, but I’d recommend working on a variety of things, paying close attention to which projects (or which parts of the project) are easy and which parts are hard. You should focus on flexibility : try not to acquire strong universal opinions about the right way to write software. What good taste I have I acquired pretty slowly. Still, I don’t see why you couldn’t acquire it fast. I’m sure there are prodigies with taste beyond their experience in programming, just as there are prodigies in other domains. Of course this isn’t always true. There are win-win changes where you can improve several usually-opposing values at the same time. But mostly we’re not in that position. Like I said above, different projects will obviously demand a different set of values. But the engineers working on those projects will still have to draw the line somewhere, and they’ll rely on their own taste to do that. That said, I do think good taste is somewhat transferable. I don’t have much personal experience with this so I’m leaving it in a footnote, but if you’re flexible and attentive to the details in domain A, you’ll probably be flexible and attentive to the details in domain B.

1 views

Consistent hashing

As a concrete experiment, I ran a similar simulation to the one above, but with 10 virtual nodes per node. We'll consider the total portion of the circle mapped to a node when it maps to either of its virtual nodes. While the average remains 18 degrees, the variance is reduced drastically - the smallest one is 11 degrees and the largest 26. You can find the code for these experiments in the demo.go file of the source code repository. This is close to the original motivation for the development of consistent caching by researchers at MIT. Their work, described in the paper "Consistent Hashing and Random Trees: Distributed Caching Protocols for Relieving Hot Spots on the World Wide Web" became the foundation of Akamai Technologies . There are other use cases of consistent hashing in distributed systems. AWS popularized one common application in their paper "Dynamo: Amazon’s Highly Available Key-value Store" , where the algorithm is used to distribute storage keys across servers.

1 views
Manuel Moreale 2 weeks ago

Kris Howard

This week on the People and Blogs series we have an interview with Kris Howard, whose blog can be found at web-goddess.org . Tired of RSS? Read this in your browser or sign up for the newsletter . The People and Blogs series is supported by Ilja Panić and the other 120 members of my "One a Month" club. If you enjoy P&B, consider becoming one for as little as 1 dollar a month. Heya! I'm Kris Howard, and as of September 2025, I've been blogging continuously for 25 years. 😳 I grew up in rural Indiana, had a couple of brief working stints in London and Munich, and have lived nearly all of my adult life in Sydney, Australia with my husband Rodd (aka The Snook). I started my career as a web developer in the dotcom boom and eventually went on to manage projects and lead teams. I ended up in Developer Relations for AWS, where I travelled all over telling folks why they should use the cloud. It was a lot of fun until everything became all about AI. In 2024 I joined the Snook in early retirement (at age 47), and for the past year I've been reading books (remember books?!), hanging out with friends, indulging in my craft hobbies (knitting, sewing, and now weaving), volunteering, travelling around Australia, and generally trying to spend a lot less time in front of a computer. I was on work-study in university, and they assigned me to work in the dining hall. That sucked , so I scrambled to find something better. I ended up working in the Computer Department just as my university was connecting everyone to the Internet. I learned HTML and built websites for myself and my dorm, and in 1996 I launched a fan site for my favourite author that's been running ever since. Fun trivia: I hosted that on roalddahl.org until the Dahl estate reached out about acquiring the domain name. I happily transferred it to them, and in return I got to meet Felicity Dahl and visit his writing hut in Buckinghamshire! By that time I had left uni and was working as a web developer in London. I started testing out Blogger (which back then would actually FTP static files to your own webhosting!) in September 2000 and launched my blog properly a couple months later at web-goddess.co.uk. The name was a bit of a joke, a nickname that a Scottish friend gave me because of how much time I spent online. Originally my goal was just to document my life overseas for friends and family, and to share silly things I found on the Internet. When the dotcom crash hit at the end of 2001, I ended up moving to Sydney with my Australian boyfriend and changed the domain to web-goddess.org instead. For a long time I ran off my own custom PHP CMS (which I even distributed ) before moving to Wordpress ten years ago. My blogging energy has waxed and waned over the years. There were long stretches when I just syndicated content from places like Instagram and Google Reader to the blog rather than write. Since retiring from full-time work I've really renewed my focus on it as the home for all my content online. I've migrated all my posts from Twitter, Instagram, and Facebook to the blog, and I now syndicate out from the blog to Mastodon and Bluesky. Every day I go back through my archives and clean up broken links. (So much linkrot.) I miss the Web of the early 2000s and I'm trying to keep my little corner of it thriving. My process is fairly casual, and I don't usually write extensive drafts before publishing. Back in the olden days, I used it basically like Twitter - just dashing off a thought or sharing a link multiple times a day. Nowadays I tend to be a bit more deliberate with what I share. Occasionally I'll get Rodd to review something, especially if it touches on our personal life (like my posts about our retirement finances ). I've occasionally dabbled with creating a series of posts on a theme, like when we tried cooking our way through the Jamie's 30 Minute Meals cookbook (still by far my most popular posts ever!). When we were living in Munich, I made a point of documenting all of our travels around Europe, knowing I'd want to look back on those trips later. I tend to write my posts in the Wordpress classic editor in a web browser. I'm comfortable with that workflow, but I've also used the Gutenberg block editor on occasion. I also occasionally post from the Wordpress app on my phone. Last year I figured out that I could post via Apple Shortcuts using the Wordpress API , which has made it really easy for me to share photos when I'm away from the computer. Definitely. We renovated our house last year and I took the opportunity to design the office-slash-craft-room of my dreams. I've got a ridiculously wide curved monitor, a super clicky Keychron mechanical keyboard , and a very silly NES mouse . I've got a comfy chair and a desk I can adjust up and down with the press of a button. I've got everything I need within arm's reach whether I'm blogging, knitting, or sewing. Having a pegboard with lots of tools on it fills a part of my soul I didn't realise was empty! I also tend to listen to music when I'm at the computer (Apple Music via Echo Dot speaker). I started out with my own hand-coded PHP-based CMS, which I used for fifteen years on various shared hosting providers. Eventually I realised that my rudimentary coding skills weren't meeting the security bar anymore, and I reluctantly let a friend persuade me try out Wordpress . To my surprise, I loved it and ended up migrating roalddahlfans.com over to it as well. It's not without its occasional headaches, but I haven't had any major problems in the last decade. During the initial months of the pandemic, I decided to migrate both sites from their shared webhosting over to Amazon Lightsail (since I was working for AWS at the time and wanted to learn more about the service). Both sites are hosted in the US and use the Wordpress blueprint on Linux (2GB memory, 2 vCPUs, 60GB SSD) with CloudFront as a CDN. The domain names were registered with Google Domains, which have since been migrated to Squarespace. For a couple years now I've been toying with the idea of converting one or both the sites to be static, served off S3 or similar. It would be a lot cheaper, faster, and more secure. The challenge is that I'm not starting from scratch; I have thousands of posts and pages that I've written over the years. I also really like being able to post from anywhere, including my phone. My husband Rodd was an SRE at Google and is a much better coder than me, so he's been working on a script that would allow us to run Wordpress from our home server and generate static HTML. We'll try it out with roalddahlfans.com and then decide where to go from there. Haha, I'd definitely choose a different name! I realised pretty early on that if you typed my domain incorrectly, nearly every other permutation was adult content. Whoops. I'd probably go with a static site today, just to keep things as simple as possible. I love the old school tiny websites that folks are building these days, and I'd go full IndieWeb - write on my site and syndicate everywhere else. I would be a bit more... considerate with how I write. I realised this year as I've been tidying up the broken links in my archives that I wasn't always kind in how I wrote about some people or topics. The early 2000s were a much snarkier time, I guess. I've chosen to leave those posts up, but I've added a disclaimer that they don't necessarily reflect who I am today. (Similarly, I've been adding a disclaimer on all my posts about Harry Potter. Rowling sucks, and it makes me sad.) I held off on monetising for many years, especially on roalddahlfans.com since most of the audience are kids. Eventually I added some hand-picked Google Ads to the site and to my blog archives, restricting the placement and ad categories. I also added Amazon affiliate links to the Dahl site, since I figured a lot of parents would be likely to buy the books. These more than covered the hosting costs over the years. (In fact, Rodd had to declare my websites when he joined Google in case there was a conflict of interest!) When we were living in Munich a few years back, I discovered that Germany has stringent tax laws about website monetisation and would require me to register as a side business. It was all too complicated, so the easiest thing was to just remove the ads. I didn't bother putting them back when we got to Australia, so for several years now there's been no income. Hosting is generally $40-50 AUD a month (for both sites), with an additional $125 AUD per site annually for Jetpack (which gives me automated backups, comment spam protection, and some other security features). This is honestly way overkill, and I reckon I can reduce that a lot in the future (especially if I move to a static site). I don't like the idea that everything on the web needs to be monetised or that everybody needs to have a side hustle. I love it when people share things online just because they want to. That's how both my sites started, and that's why I keep them going. That said, I financially support a couple bloggers and my Mastodon instance admin via Patreon, because I want them to continue. So many sites disappear, and it's just sad. One of the people I think of when I think of blogging is Matt Haughey from A Whole Lotta Nothing: a.wholelottanothing.org . He was the founder of Metafilter.com , and I think I've been reading his site for literally decades now. He was there when blogging was invented. Definitely someone worth talking to! Does a newsletter count as a blog these days? The person whose words have given me the most hope for humanity in 2025 is Mike Monteiro . Every time he writes it's just so, so good and I end up blogging it or sending it around to all my friends. (Archives are here .) I've also been really enjoying the blog of Robb Knight: rknight.me . He built Echofeed , the service I use to syndicate my blog posts out to Mastodon and Bluesky. He's always building something nerdy, or geeking out over pens and stationery. This is so absolutely dorky, but I am currently reading the Aubrey-Maturin "Master and Commander" books . I always figured they were quintessential "Dad books" (given they are historical fiction about naval voyages in the Napoleonic Wars) and therefore Not For Me, but this amazing essay convinced me to give them a shot. I've discovered that the books themselves are fantastic, and there's this whole fandom subculture I never knew about! They refer to reading the series as a "circumnavigation," and there are charming map websites and podcasts and subreddits with fans all talking (in character!) about the books. I'm loving it. It's been a welcome escape from the news over the past few months, and I can highly recommend the series. Now that you're done reading the interview, go check the blog and subscribe to the RSS feed . If you're looking for more content, go read one of the previous 108 interviews . Make sure to also say thank you to Markus Heurung and the other 120 supporters for making this series possible.

0 views
DYNOMIGHT 2 weeks ago

Shoes, Algernon, Pangea, and Sea Peoples

I fear we are in the waning days of the People Read Blog Posts About Random Well-Understood Topics Instead of Asking Their Automatons Era. So before I lose my chance, here is a blog post about some random well-understood topics. You probably know that people can now run marathons in just over 2 hours. But do you realize how insane that is? That’s an average speed of 21.1 km per hour, or 13.1 miles per hour. You can think of that as running a mile in 4:35 (world record: 3:45 ), except doing it 26.2 times in a row. Or, you can think of that as running 100 meters in 17.06 seconds (world record: 9.58 seconds ), except doing it 421.6 times in a row. I’d guess that only around half of the people reading this could run 100 meters in 17.06 seconds once . This crazy marathon running speed is mostly due to humans being well-adapted for running and generally tenacious. But some of it is due to new shoes with carbon-fiber plates that came out in the late 2010s. The theory behind these shoes is quite interesting. When you run, you mainly use four joints: If you haven’t heard of the last of these, they’re pronounced “ met -uh-tar-so-fuh- lan -jee-ul” or “MTP”. These are the joints inside your feet behind your big toes. Besides sounding made-up, they’re different from the other joints in a practical way: The other joints are all attached to large muscles and tendons that stretch out and return energy while running sort of like springs. These can apparently recover around 60% of the energy expended in each stride. (Kangaroos seemingly do even better .) But the MTP joints are only attached to small muscles and tendons, so the energy that goes into them is mostly lost. These new shoe designs have complex constructions of foam and plates that can do the same job as the MTP joints, but—unlike the MTP joints—store and return that energy to the runner. A recent meta-analysis estimated that this reduced total oxygen consumption by ~2.7% and marathon times by ∼2.18%. I wonder if these shoes are useful as a test case for the Algernon argument . In general, that argument is that there shouldn’t be any simple technology that would make humans dramatically smarter, since if there was, then evolution would have already found it. You can apply the same kind of argument to running: We have been optimized very hard by evolution to be good at running, so there shouldn’t be any “easy” technologies that would make us dramatically faster or more efficient. In the context of the shoes, I think that argument does… OK? The shoes definitely help. But carbon fiber plates are pretty hard to make, and the benefit is pretty modest. Maybe this is some evidence that Algernon isn’t a hard “wall”, but rather a steep slope. Or, perhaps thinking is just different from running. If you start running , you will get better at it, in a way that spills over into lots of other physical abilities. But there doesn’t seem to be any cognitive task that you can practice and make yourself better at other cognitive tasks. If you have some shoes that will make me 2.7% smarter, I’ll buy them. Pangea was a supercontinent that contained roughly all the land on Earth. At the beginning of the Jurassic 200 million years ago, it broke up and eventually formed the current continents. But isn’t the Earth 4.5 billion years old? Why would all the land stick together for 95% of that time and then suddenly break up? The accepted theory is that it didn’t. Instead, it’s believed that Earth cycles between super-continents and dispersed continents, and Pangea is merely the most recent super-continent. But why would there be such a cycle? We can break that down into two sub-questions. First, why would dispersed continents fuse together into a supercontinent? Well, you can think of the Earth as a big ball of rock, warmed half by primordial heat from when the planet formed and half by radioactive decay. Since the surface is exposed to space, it cools, resulting in solid chunks that sort of slide around on the warm magma in the upper mantle. Some of those chunks are denser than others, which causes them to sink into the mantle a bit and get covered with water. So when a “land chunk” crashes into a “water chunk”, the land chunk slides on top. But if two land chunks crash into each other, they tend to crumple together into mountains and stick to each other. You can see this by comparing this map of all the current plates: To this map of elevation: OK, but once a super-continent forms, why would it break apart? Well, compared to the ocean floor, land chunks are thicker and lighter. So they trap heat from inside the planet sort of like a blanket. With no cool ocean floor sliding back into the warm magma beneath, that magma keeps getting warmer and warmer. After tens of millions of years, it heats up so much that it stretches the land above and finally rips it apart. It’s expected that a new supercontinent “Pangea Ultima” will form in 250 million years. By that time, the sun will be putting out around 2.3% more energy, making things hotter. On top of that, it’s suspected that Pangea Ultima, for extremely complicated reasons , will greatly increase the amount of CO₂ in the atmosphere, likely making the planet uninhabitable by mammals. So we’ve got that going for us. The Sea Peoples are a group of people from… somewhere… that appeared in the Eastern Mediterranean around 1200 BC and left a trail of destruction from modern Turkey down to modern Egypt. They are thought to be either a cause or symptom of the Late Bronze Age collapse . But did you know the Egyptians made carvings of the situation while they were under attack? Apparently the battle looked like this : In the inscription, Pharaoh Ramesses III reports: Those who reached my boundary, their seed is not; their hearts and their souls are finished forever and ever. As for those who had assembled before them on the sea, the full flame was their front before the harbor mouths, and a wall of metal upon the shore surrounded them. They were dragged, overturned, and laid low upon the beach; slain and made heaps from stern to bow of their galleys, while all their things were cast upon the water. Metatarsophalangeal

0 views
Sean Goedecke 2 weeks ago

Endless AI-generated Wikipedia

I built an infinite, AI-generated wiki. You can try it out at endlesswiki.com ! Large language models are like Borges’ infinite library . They contain a huge array of possible texts, waiting to be elicited by the right prompt - including some version of Wikipedia. What if you could explore a model by interacting with it as a wiki? The idea here is to build a version of Wikipedia where all the content is AI-generated. You only have to generate a single page to get started: when a user clicks any link on that page, the page for that link is generated on-the-fly, which will include links of its own. By browsing the wiki, users can dig deeper into the stored knowledge of the language model. This works because wikipedias 1 connect topics very broadly. If you follow enough links, you can get from any topic to any other topic. In fact, people already play a game where they try to race from one page to a totally unrelated page by just following links. It’s fun to try and figure out the most likely chain of conceptual relationships between two completely different things. In a sense, EndlessWiki is a collaborative attempt to mine the depths of a language model. Once a page is generated, all users will be able to search for it or link it to their friends. The basic design is very simple: a MySQL database with a table, and a Golang server. When the server gets a request, it looks up in the database. If it exists, it serves the page directly; if not, it generates the page from a LLM and saves it to the database before serving it. I’m using Kimi K2 for the model. I chose a large model because larger models contain more facts about the world (which is good for a wiki), and Kimi specifically because in my experience Groq is faster and more reliable than other model inference providers. Speed is really important for this kind of application, because the user has to wait for new pages to be generated. Fortunately, Groq is fast enough that the wait time is only a few hundred ms. Unlike AutoDeck , I don’t charge any money or require sign-in for this. That’s because this is more of a toy than a tool, so I’m not worried about one power user costing me a lot of money in inference. You have to be manually clicking links to trigger inference. The most interesting design decision I made was preventing “cheating”. I’m excited to see how obscure the pages can get (for instance, can you get to eventually get to Neon Genesis Evangelion from the root page?) It would defeat the purpose if you could just manually go to in the address bar. To defeat that, I make each link have a query parameter, and then I fetch the origin page server-side to validate that it does indeed contain a link to the page you’re navigating to 2 . Like AutoDeck , EndlessWiki represents another step in my “what if you could interact with LLMs without having to chat” line of thought. I think there’s a lot of potential here for non-toy features. For instance, what if ChatGPT automatically hyperlinked each proper noun in its responses, and clicking on those generated a response focused on that noun? Anyway, check it out! I use the lowercase “w” because I mean all encyclopedia wikis. Wikipedia is just the most popular example. Interestingly, Codex came up with five solutions to prevent cheating, all of which were pretty bad - way more complicated than the solution I ended up with. If I was purely vibe coding, I’d have ended up with some awkward cryptographic approach.

5 views
Anton Zhiyanov 2 weeks ago

Go proposal: new(expr)

Part of the Accepted! series, explaining the upcoming Go changes in simple terms. Allow the built-in to be called on expressions. Ver. 1.26 • Language • High impact Previously, you could only use the built-in with types: Now you can also use it with expressions: If the argument is an expression of type T, then allocates a variable of type T, initializes it to the value of , and returns its address, a value of type . There's an easy way to create a pointer to a composite literal: But no easy way to create a pointer to a value of simple type: The proposal aims to fix this. Update the Allocation section of the language specification as follows: The built-in function creates a new, initialized variable and returns a pointer to it. It accepts a single argument, which may be either an expression or a type. ➀ If the argument is an expression of type T, or an untyped constant expression whose default type is T, then allocates a variable of type T, initializes it to the value of , and returns its address, a value of type . ➁ If the argument is a type T, then allocates a variable initialized to the zero value of type T. For example, and each return a pointer to a new variable of type int. The value of the first variable is 123, and the value of the second is 0. ➀ is the new part, ➁ already worked as described. Pointer to a simple type: Pointer to a composite value: Pointer to the result of a function call: Passing is still not allowed: 𝗣 45624 • 𝗖𝗟 704935 , 704737 , 704955 , 705157

0 views
Anton Zhiyanov 2 weeks ago

Accepted! Go proposals distilled

I'm launching a new Go-related series named Accepted! For each accepted proposal, I'll write a one-page summary that explains the change in simple terms. This should (hopefully) be the easiest way to keep up with upcoming changes without having to read through 2,364 comments on Go's GitHub repo. Here's a sneak peak: The plan is to publish the already accepted proposals from the upcoming 1.26 release, and then publish new ones as they get accepted. I'll probably skip the minor ones, but we'll see. Stay tuned!

0 views
Anton Zhiyanov 3 weeks ago

Native threading and multiprocessing in Go

As you probably know, the only way to run tasks concurrently in Go is by using goroutines. But what if we bypass the runtime and run tasks directly on OS threads or even processes? I decided to give it a try. To safely manage threads and processes in Go, I'd normally need to modify Go's internals. But since this is just a research project, I chose to (ab)use cgo and syscalls instead. That's how I created multi — a small package that explores unconventional ways to handle concurrency in Go. Features • Goroutines • Threads • Processes • Benchmarks • Final thoughts Multi offers three types of "concurrent groups". Each one has an API similar to , but they work very differently under the hood: runs Go functions in goroutines that are locked to OS threads. Each function executes in its own goroutine. Safe to use in production, although unnecessary, because the regular non-locked goroutines work just fine. runs Go functions in separate OS threads using POSIX threads. Each function executes in its own thread. This implementation bypasses Go's runtime thread management. Calling Go code from threads not created by the Go runtime can lead to issues with garbage collection, signal handling, and the scheduler. Not meant for production use. runs Go functions in separate OS processes. Each function executes in its own process forked from the main one. This implementation uses process forking, which is not supported by the Go runtime and can cause undefined behavior, especially in programs with multiple goroutines or complex state. Not meant for production use. All groups offer an API similar to . Runs Go functions in goroutines that are locked to OS threads. starts a regular goroutine for each call, and assigns it to its own thread. Here's a simplified implementation: goro/thread.go You can use channels and other standard concurrency tools inside the functions managed by the group. Runs Go functions in separate OS threads using POSIX threads. creates a native OS thread for each call. It uses cgo to start and join threads. Here is a simplified implementation: pthread/thread.go You can use channels and other standard concurrency tools inside the functions managed by the group. Runs Go functions in separate OS processes forked from the main one. forks the main process for each call. It uses syscalls to fork processes and wait for them to finish. Here is a simplified implementation: proc/process.go You can only use to exchange data between processes, since regular Go channels and other concurrency tools don't work across process boundaries. Running some CPU-bound workload (with no allocations or I/O) on Apple M1 gives these results: And here are the results from GitHub actions: One execution here means a group of 4 workers each doing 10 million iterations of generating random numbers and adding them up. See the benchmark code for details. As you can see, the default concurrency model ( in the results, using standard goroutine scheduling without meddling with threads or processes) works just fine and doesn't add any noticeable overhead. You probably already knew that, but it's always good to double-check, right? I don't think anyone will find these concurrent groups useful in real-world situations, but it's still interesting to look at possible (even if flawed) implementations and compare them to Go's default (and only) concurrency model. Check out the nalgeon/multi repo for the implementation. P.S. Want to learn more about concurrency? Check out my interactive book

0 views
Dayvster 3 weeks ago

Are We Chasing Language Hype Over Solving Real Problems?

## Intro As you may have heard or seen, there is a bit of controversy around Ubuntu adopting a rewritten version of GNU Core Utils in Rust. This has sparked a lot of debate in the tech community. This decision by Canonical got me thinking about this whole trend or push of rewriting existing software in Rust which seems to be happening a lot lately. To put it bluntly I was confused by the need to replace GNU Core Utils with a new implementation as GNU Core Utils has been around since arguably the 90s and more realistically 2000s and it has been battle tested and proven to be reliable, efficient, effective and most importantly secure as it had basically never had any major security vulnerabilities in its entire existence. So why then would we deem it necessary to replace it with a new implementation in Rust? Why would anyone go through the trouble of rewriting something that already works perfectly fine and has been doing so for decades? When the end result at best is going to be a tool that does the same thing as the original and in the very best case scenario offer the same performance? What bothers me even more is the bigger pattern this points to. Are we as developers more interested in chasing new languages and frameworks than actually solving real problems? I strongly subscribe to the idea that software development 60% problem solving and 40% creative exploration and innovation. But lately it feels like the balance is shifting more and more towards the latter. We seem to be more interested in trying out the latest and greatest languages and frameworks than actually solving real problems. ## The Hype of New Languages and Shiny Object Syndrome We've all been there in the past haven't we? Getting excited about a new programming language or framework that promises to solve all our problems and make our lives easier. It's easy to get caught up in the hype and want to try out the latest and greatest technology, but it's important to remember that just because something is new doesn't mean it's better. We need to be careful not to fall into the trap of "shiny object syndrome" where we chase after the latest trends without considering whether they actually solve our problems or improve our workflows. It's important to evaluate new technologies based on their merits and how they fit into our existing systems and workflows, rather than simply jumping on the bandwagon because everyone else is doing it. Now for the important question: **Do I think the developers of coreutils-rs are doing this just because Rust is the new hotness?** Short and simple: No, no I do not. I believe they have good intentions and are likely trying to improve upon the existing implementation in some way. However, I do not agree with them that there is a need for a rewritten version of GNU Core Utils in Rust. I also do not agree that GNU Core Utils is inherently insecure or unsafe. ### Why do we get Exited About New Languages? It's also important to briefly touch upon the psychological aspect of why we get excited about new languages. New languages often come with new features, syntax, and paradigms that can be appealing to developers. They may also promise to solve problems that existing languages struggle with, such as performance, concurrency, or memory safety. Additionally, new languages can offer a fresh perspective on programming and can inspire creativity and innovation. Not to mention the community aspect, new usually means a changing of the guard, new people, new ideas, new ways of thinking about problems. All of these factors can contribute to the excitement and enthusiasm that developers feel when a new language is introduced. This enthusiasm can sometimes lead to an almost zealous approach of wanting everything and anything to be written only in the new language by this new and fresh community of developers. This can lead to a situation where existing and well-established software is rewritten in the new language, even if there is no real need for it. This can be seen as a form of "language evangelism" where developers are trying to promote their favorite language by rewriting existing software in it. ## The Case of GNU Core Utils As I've briefly touched upon earlier, GNU Core Utils is a collection of basic file, shell and text manipulation utilities that are fundamental to the operation of Unix-like operating systems. These utilities include commands like `ls`, `cp`, `mv`, `rm`, `cat`, `echo`, and many others. They are essential for performing everyday tasks in the command line interface (CLI) and are used by system administrators, developers, and users alike. Some of these can run hundreds of times per second, so performance is absolutely crucial. Even a small reduction in performance to a utility that is run by some OS critical daemon can have a significant impact on the overall performance of the system. GNU core utils has been optimized for this for about 30+ years at this point and is it really worth just tossing all of those lessons and optimizations out the window just to rewrite it in a new language? I've also briefly touched upon that at best in the absolute **best case scenario** a rewritten version of GNU Core Utils in Rust would be able to match the performance of the original implementation. As we know GNU Core Utils are mostly written in C and some C++ mixed in sparingly. So far benchmarks have shown time and time again that at best with a lot of optimizations and tweaks Rust can only ever match the performance of C and in most cases it is actually slower. So the best case outcome of this rewrite is that we get a tool that does the same thing as the original and at best offers the same performance. So what is the actual benefit of this rewrite? Where is the value, what is the actual problem that is being solved here? ## When Hype Overshadows Real Problems This is the crux of the issue, it's very very easy to get swept up in the excitement of a new language and want to use it for everything and anything under the sun. As developers we love novelty and communities with enthusiasm and fresh ideas. It's stimulating it's fun it feels like progress it feels like we are finally building something again instead of just rehashing and maintaining. We all know from personal experience that creating a new project is more fun and enjoyable than maintaining and existing one and this is a natural human tendency. Now do I think this is one of the reasons the developers of coreutils-rs are doing this? Yes, I do. But in the end they are solving a problem that does not exist. ### It's not just about Core Utils Now with how often I've mentioned this specific example of GNU Core Utils you might think I want to single them out or have some sort of grudge or specific issue with this particular project. No, not really... I think this project is indicative of the larger issue we face in the tech community. It's very easy to get caught up in the excitement of new languages and frameworks and want to use them for everything and anything. This can lead to a situation where we are rewriting existing software in new languages without considering whether it actually solves any real problems or improves our workflows. ## Problem Solving Should Be Our North Star At the end of the day, software development is about solving real problems, not about chasing novelty, shiny new languages, or personal curiosity. Every line of code we write, every framework we adopt, every library we integrate should be justified by the problems it helps solve, not by the hype around it. Yet increasingly, it feels like the industry is losing sight of this. We celebrate engineers for building in the “new hot language,” for rewriting tools, or for adopting the latest framework, even when the original solution worked perfectly fine. We reward novelty over necessity, excitement over impact. This is not a phenomenon isolated to just core utils or systems programming, it happens in web development, mobile development, data science, and pretty much every other area of software development. We too often abandon tried and true solutions and ideas of new and exciting shiny ones without considering whether they actually solve any real problems or improve our workflows. For example web development went full circle with React Server Components where we went from separation of concerns straight back to PHP style mixing of HTML and logic, server rendering and delivering interactive components to the client. Or the whole GraphQL craze where traditional REST APIs were abandoned en masse for a new and exciting way of doing things that promised to solve the dreaded problem of "over-fetching" and "under-fetching" of data. Yet in reality, it introduced a whole new set of problems and complexities that were not present in traditional REST APIs. Or perhaps the whole microservices and microfrontend craze where a lot of projects were abandoned or rewritten to be split into smaller and smaller pieces, **Was it all bad? Should we always just stick to what works and only ever maintain legacy projects and systems? Heck no!** There is definitely a place for innovation and new ideas in software development. New languages, frameworks, and tools can bring fresh perspectives and approaches to problem-solving. However, it's important to evaluate these new technologies based on their merits and how they fit into our existing systems and workflows, rather than simply jumping on the bandwagon because everyone else is doing it. We need to be more critical and thoughtful about the technologies we adopt and the projects we undertake. We need to ask ourselves whether a new language or framework actually solves a real problem or improves our workflows, or if we're just chasing novelty for its own sake. ## A Final Thought At the end of the day, it’s not about Rust, React, GraphQL, or the latest microservices fad. It’s about solving real problems. Every line of code, every framework, every rewrite should have a purpose beyond curiosity or hype. We live in a culture that rewards novelty, celebrates “cool” tech, and often mistakes excitement for progress. But progress isn’t measured in how many new languages you touch, or how many shiny rewrites you ship, it’s measured in impact, in the problems you actually solve for users, teams, and systems. So next time you feel the pull of the newest hot language, framework, or tool, pause. Ask yourself: “Am I solving a real problem here, or just chasing excitement?” Because at the end of the day, engineering isn’t about what’s trendy, it’s about what works, what matters, and what actually makes a difference. And that, my friends, is the craft we should all be sharpening.

0 views
DHH 4 weeks ago

As I remember London

As soon as I was old enough to travel on my own, London was where I wanted to go. Compared to Copenhagen at the time, there was something so majestic about Big Ben, Trafalgar Square, and even the Tube around the turn of the millenium. Not just because their capital is twice as old as ours, but because it endured twice as much, through the Blitz and the rest of it, yet never lost its nerve

0 views
iDiallo 1 months ago

Which LLM Should I Use as a Developer?

Early in my career, I worked alongside a seasoned C programmer who had finally embraced web development. The company had acquired a successful website built in Perl by someone who, while brilliant, wasn't entirely technical . The codebase was a fascinating mess. commands interwoven with HTML, complex business logic, database calls, and conditional statements all tangled together in ways that would make you want to restart from scratch! Then came the JavaScript requirements. Whenever frontend interactions needed to be added, animations, form validations, dynamic content, I became the go-to person. Despite his deep understanding of programming fundamentals, JavaScript simply didn't click for this experienced developer. The event-driven nature, the prototype-based inheritance, the asynchronous callbacks? They made no sense to him. I was young when I picked up JavaScript, still malleable enough to wrap my head around its quirks. Looking back, I sometimes wonder: if my introduction to programming had been through React or Vue rather than simple loops and conditionals, I would have chosen a different career path entirely. Fast-forward to today, and that same experienced programmer would likely sail through JavaScript challenges without breaking a sweat. Large Language Models have fundamentally changed the game for developers working with unfamiliar languages and frameworks. LLMs can scaffold entire functions, components, or even small applications in languages you've never touched. More importantly, if you're not lazy about it , you can read through the generated code and understand the patterns and idioms of that language. When you inevitably write buggy code in an unfamiliar syntax, LLMs excel at debugging and explaining what went wrong. They're like having a patient mentor who never gets tired of explaining the same concept in different ways. For example, I'm not very good with the awk command line tool, but I can write what I want in JavaScript. So I would often write how I want to parse content in JavaScript and ask an LLM to convert it to awk. Let's say I want to extract just the user agent from Apache log files. In JavaScript, I might think about it like this: The LLM converts this to: It uses the quote character as a field separator and prints the second-to-last field (since the last field after the final quote is empty). This kind of translation between mental models is where LLMs truly shine. Until recently, new developers would approach me with the question: "What's the best programming language to learn?" My response was always pragmatic: "It depends on what you're trying to build. It doesn't really matter." But they'd follow up with their real opinion: "I think Python is the best." The concept of a "best programming language" never entirely made sense to me. I might love Python's elegance, but I still need JavaScript for frontend work, SQL for databases, and bash for deployment scripts. The job dictates the tool, not the other way around. Today, something fascinating is happening. Developers aren't asking about the best programming language anymore. Instead, I hear: "Which is the best LLM for coding?" My answer remains the same: It doesn't really matter. The internet is awash with benchmarks, coding challenges, and elaborate metrics attempting to crown the ultimate coding LLM. These tests typically focus on "vibe coding". They try to generate complete solutions to isolated problems from scratch. If that's your primary use case, fine. But in my experience building real applications that serve actual users, I've rarely found opportunities to generate entire projects. Instead, I see myself asking questions to old pieces of code to figure out why the original developer made a decision to implement a function one way. I generate util functions with an LLM, I ask to generate those extremely annoying TypeScript interfaces (Life is too short to manually write that out). To my knowledge, all LLMs can perform these tasks at an acceptable level that I can immediately test and validate. You don't need AGI for this. After programming for over three decades, I've learned that picking up new languages isn't particularly challenging anymore. The fundamental goal of making computers do useful things, remains constant. What changes is syntax, idioms, and the philosophical approaches different language communities embrace. But when you're starting out, it genuinely feels like there must be one "optimal" language to learn. This illusion persists because beginners conflate syntax familiarity with programming competence. The truth is more nuanced. Even expert C programmers can struggle with JavaScript, not because they lack skill, but because each language embodies different mental models. The barriers between languages are dissolving, and the cost of experimenting with new technologies is approaching zero. The LLM you choose matters far less than developing the judgment to evaluate the code it produces. Pick any reputable LLM, learn to prompt it effectively, and focus on building things that matter. The rest is just syntax. Don't start with a language; start with a problem to be solved. — Matt Mullenweg

0 views
Brain Baking 1 months ago

A Tribute To Hoyle's Official Book Of Games

In 1989, Sierra On-Line released Volume 1 of their Hoyle: Official Book of Games on MS-DOS, a card game collection where you could play Crazy Eights, Old Maid, Hearts, Gin Rummy, Cribbage, and Klondike Solitaire according to Edmond Hoyle’s rules as recorded in his foundational work Hoyle’s Rules Of Games . Hoyle meticulously recorded and explained all games “of skill and chance” he encountered from as early as 1672, including expert advice on strategies and even how to settle disputes. Sierra managed to procure a license boasting the name Hoyle not only in the title but also in some of the card faces that USA manufacturers Brown & Bigelow branded Hoyle —hence the addition of “official”. The most remarkable aspect of this game is that you can play not only against typical Sierra characters such as Larry Laffer and King Graham, but also against Sierra employees from that time and their children! Your opponents are quick to quip and laugh at the one swallowing the queen of spades in the game of Hearts, with their animated faces showcasing that grin or unpleasant surprise. Hoyle: Official Book of Games is a typical Sierra game from that time that oozes CGA charm. Gerald Moore, one of the artists, would go on and work for various Police Quest and Quest For Glory Sierra games. The screenshot below also shows the typical Sierra menu bar on top, proving that Sierra indeed repurposed their Sierra Creative Interpreter engine for these volumes. A Hearts session in play with off-topic banter going on trigged by my inactivity. This can be turned off, but why would you want to strip out the personality? As for the gameplay itself, it was a bit bare-bones. The card game mechanics do not differ from the later Hearts implementations, but the absence of quality of life features such as the ability to auto-sort your cards or to inspect the last trick make it a bit harder to enjoy these days. Clicking and dragging those cards around in your hand to sort them by hand is painful, and I have a lot of difficulties discerning the differences between spades and clubs. Luckily, the friendly AI player will remind me to follow suit. Hearts is also the only trick taking game present. In 1990 and 1991, Sierra released Volume 2 and 3 of their Hoyle: Official Book of Games , this time focusing on solitaire card games and simple board games using the same engine and characters as seen and loved in the first volume. The characters would go on to be a key feature in future release and would set them apart from competing card game collections on the PC. After all, implementing Hearts is trivial, but injecting a doze of charm and fun is what makes the difference. In 1993, Sierra completely revamped Volume 1 to account for the VGA evolution, resulting in more shiny colours, Adlib-compatible musical tones, and a few more characters/games in Hoyle Classic Card Games . Let’s call this Hoyle 4 . This time, we’re finally treated with two more trick taking games: Contract Bridge and Euchre. A Hoyle 4 session in play showcasing the VGA upgrade. The card faces and table backdrop is customizable. Sierra yet again put in effort to up the charm ante by digitizing some of the compliments and taunts, and having characters making fun of each other during loading screens. Hoyle 4 would be the last one featuring the Sierra characters though, as the subsequent versions culled them in favour of more general but equally goofy ones. Maybe to appeal to a new audience or maybe because of license issues as Sierra prepared to shed their On-Line past during the major reorganization that shut down multiple studios resulting in layoffs and focus shifts. The Hoyle branding would never make it back on the top priority list, even though they happily kept on churning out repackages. All the older DOS versions are playable right in your browser at Classics Reloaded with a little bit of help from the embedded DOSBox version, in case you’re curious to see how Larry pulls of his tricks instead of pants. I changed the card faces of the above screenshot to something more curvy just for him. That smile on his face says it all. In 1997, the game got yet another reskin when everybody insisted on running Windows programs ( Hoyle 5 ), and yet another in 2002 ( Hoyle 6 ) that added a fresh lick of paint to the UI. Even though these later releases might feel like quick cash grabs, Hoyle 5 did come with quite a lot of new card game variants including solitaire options such as Klondike that was popularized by Windows 3’s Solitaire . You do remember the spooky dark castle card backs designed by Susan Kare in 1990, do you? Hoyle 6 , rebranded as Hoyle Card Games (2002) , is the game I probably played the most, and you can too: the is available on , and using CrossOver, it even runs on macOS: Playing a round of Spades in Hoyle Card Games 2002 on a Brain Baking website background. If you keep the mounted, the atrocious background music that thankfully can be turned off will play, but more importantly, the characters’ voices that lend them their charm will be present as well. That old crow Ethel can be a particularly sore loser at Spades if Elayne and I are on a roll. Later releases beyond version six introduced very little new games and/or changes. The series went downhill pretty fast after a questionable series of Sierra restructurings and layoffs, but it’s still alive: there’s a Steam version with butt-ugly static 3D renders of boring characters while the ones we grew attached to were kicked out. Unsurprisingly, the game got review-hammered on Valve’s platform. Sierra tried to dip a toe in handheld card game releases exactly once. Developed by Sandbox Studios in 2000, Hoyle Card Games was released on the Game Boy Color but never made it to Europe. With 8 card games and 6 solitaire variants, the game is decent enough, even supporting multiplayer link cable mode. Even though Edmond Hoyle’s paper rulebook contains a chapter called Klaberjass —I have no idea why so many foreigners think German is the same as Dutch—due to its relative obscurity outside of Belgium and The Netherlands, the card game variant never made it into the video game. In fact, the Nintendo DS game 18 Classic Card Games made by a German studio is the only one I could get my hands on that includes Klaverjassen , but I would strongly advice against playing that game. It is surprisingly difficult to find out which edition contained the Klaberjass addition as Hoyle’s Official Rules saw more than fifty editions and even more re-releases throughout the last few centuries. No mention of Wiezen either, but the first booklet Hoyle ever published in 1742 was called A Short Treatise on the Game of Whist, Containing the Laws of the Game, and Some Rules Whereby a Beginner May, with Due Attention to Them, Attain to the Playing It Well. What a great and informative title. Hoyle’s books would go on to be all-time best-sellers in the eighteenth century—not bad for a lawyer’s side hustle. This article is part two in a series on trick taking and card games . See also: part one on The Flemish Trick Taking Tradition . Stay tuned for the next part! Related topics: / card games / trick taking / screenshots / By Wouter Groeneveld on 11 September 2025.  Reply via email .

0 views
Karboosx 1 months ago

A Few Tricks to Make LLMs Hallucinate Less

How do you stop your LLM from going off the rails? You can't, but you can build a better system around it. Here are my go-to techniques for making AI apps more reliable.

0 views