Choose Boring Technology and LLMs
maragu.dev
maragu.dev
I worry overall that this could signal the complete end of new programming languages except in a few special cases. (Which I think was already a worrying trend before AI- see Bret Victor’s “The Future of Programming” talk).
It could be even something that the larger and slower AI model is defining and implementing the APIs and smaller and faster is the one who will actually make use of those.
Or some variations of those combined, where it's a single AI model with a capability to select between the 2. If it's complicated APIs, it will try to crawl the docs for accuracy and make "AI intuitive" wrappers around all of the APIs and their edge cases, and making it easier for the fast model.
E.g. right now I think AI is excellent with JavaScript/TypeScript, but worse with some other languages like e.g. Rust or Scala.
And maybe if the LLM sometimes tries to use different naming, you could add an overload of the same API end point, as long as it doesn't clash with an existing one. So in the end for anyone using your library with an LLM it would appear to just work.
I noticed that letting GPT-4 write more of the code had the advantage that it understood it better and less context was necessary.
Now when I design systems for GPT-4 itself to use, I just let GPT-4 design them. Ask it to use an imaginary system, and what it comes up with (consistently) should be the API.
Those efficiencies will eventually be driven into all parts of the system. AI will be able to run the most efficient code on the most efficiently designed processors, that can be designed with the knowledge that only AI is going to use them. And then we can remove ALL the weird abstractions and accommodations we had to make for human brains.
I’m not saying it will happen tomorrow but language choice is just a temporary concern.
It’s based on human code, most of that isn’t efficient.
I mean, by that logic, languages like Rust and Golang should never have taken off. Yet we see improvement due to their invention and adoption. Limiting programming language design and theory will rob us of a lot of potential improvements we could achieve at some point.
Also, old languages can be improved still. Java has some gotchas that will probably forever be fossilized into the language, but it still managed to get algebraic data types, proper pattern matching, virtual threads, etc.
Also, add to it Brook's famous paper and we can see that "new, modern" language will fail to account for even single digit productivity improvements, let alone order of magnitude differences. Me adding an already working, battle-tested dependency is the only real productivity booster.
(Nonetheless, I'm absolutely not against change, and I absolutely love language design as a topic. I just think that any language that wants to live in its own hermetic world has to give a really good reason for that choice)
Good libraries for everything commonly done server side in web dev. Google people write the libraries, and they're used within Google, so even the obscure cases are executed frequently. If your problem is a variation on a common theme, not only can Go probably do it, common LLMs will know how to make Go do it.
Go gives up a little performance in exchange for simplifying some problems that give many programmers trouble. It's garbage collected, which simplifies ownership, and its goroutines can safely block, so you don't have the async/sync distinction. Since LLMs don't really understand either of those issues, this makes LLM-driven coding work better.
Remember, LLM based coding is about as good as copy-pasting from Stack Overflow. It only works well in areas where there's something it can copy and mod. Usually, if you search for names in LLM-generated code, you can find where it located a prototype to copy from.
Java is also GCd with significantly better implementationS, they have far better throughput, and they also have a low-latency one where pause time is actually decoupled from heap size, unlike what Go does with simply blocking threads under load.
Also, Java has virtual threads which are the same as go routines, so not even that is a relevant difference.
And due to it being a bigger language, more of it will be found in LLM data sets, ergo LLMs will more useful in case of Java.
Possibly? I mean, for certain kinds of systems (most of the CRUD stuff out there) having some boring technologies and frameworks that are fairly stable and get security updates is probably preferable, even if they're not the most modern or stylish to use. And since the Lindy effect seems to have some truth to it, those might also help with picking something that will probably still be around in 5-10 years.
Think Java with Spring Boot, C# with ASP.NET, Ruby with Rails, Python with Django, PHP with Laravel, Node with Express.js and so on.
> I mean, by that logic, languages like Rust and Golang should never have taken off.
In my country, they mostly haven't. Most of the job postings are for the languages and frameworks above, there's actually very little in the way of modern tech stacks, so it probably depends on where you're located - tech hubs (or idk, research in academia) will allow for shinier technologies vs something more boring and conventional!
Anything of decent value and well design will be adapted and continue to be built. But anything without decent marketing power will die anyways regardless and only get adapted because it felt cool to that random engineer no.1 who wanted to pad there CV quickly before jumping onto next big money machine.
Show me the mass adaptation of Nim/F#/Scala(decently mature)/Crystal/Odin etc and I’ll understand your points.
Go is a different league compared to the ones I mentioned.
But Go wasn't really the point of the article, so maybe we shouldn't be here doing language flamewars? :D
Nevermind getting a newer language with new useful concepts, can we just have a tooling ecosystem that isn't broken!
I would suggest trying a different ecosystem entirely. I chose Go's, but there are many alternatives not nearly as broken, and in some cases working quite nicely.
I agree with his main thesis which is that we can do better to improve on some of these literally 60 year old programming and programming tooling paradigms.
I'm hoping that the paradigm improvement isn't to just paste over the entire endeavour with some AI agents that abstract away coding as we currently think about it.
I’ll admit Go and Typescript come close though.
I do think that an LLM today could understand the basics of a language it's never seen before (as long as it's at least somewhat related to a current language). But the AI's code writing abilities will be limited. For example I can ask ChatGPT to tell me if a code example is Pythonic.
A slightly different extension of your example would be to ask if recipe writing will be ended forever. The AI basically understands the rules / patterns of how food ingredients are combined together with which techniques. Will anyone bother to write down new recipes anymore in the future if the AI can do just as well? If someone publishes a new recipe it needs to spread prolifically enough on the internet before the AI understands it as a fundamental concept. What do we lose if this is the case?
I don't think anything has changed in this regard. Yes we have a small number of success stories like elixir or rust, and then we have a few corporate backed success stories like go, swift and kotlin. But that has always been a tiny fraction of the "promising new programming language" space.
Companies have always been conservative about choice of programming language and I don't think that will get any worse now.
The kinds of people who would have in the past tried a new and unproven language are still there and they're unlikely to stop trying new and unproven languages just because AI doesn't know them.
I for sure am not going to stop looking at weird new and/or obscure languages just because AI struggles with them.
Programming often involves creating new languages (or APIs) (like domain specific languages) on top of lower level languages (like the base programming language you use).
Future AIs should be able to learn new languages, else they would remain pretty limited.
If Apple were to come out with Swift today and were to fine-tune an LLM or just put the docs / code samples / repos /PRs in context I don't think the LLM would understand as much about the language as it does about other widely talked about languages.
One of my most impressive uses is for performance optimisation. Claude implemented efficient byte conversion to bigint, and I pasted Julia’s bignum standard base library file, `gmp.jl` to figure out how to do so [1]. Then, a Jacobi symbol calculation function was completely optimised with Calude, and I interactively provided feedback on the functions, correctness, and profiler information on which lines most of the time is spent [2].
Additionally, the OpenSSL wrapper for elliptic curve operations would be beyond my expertise if I hadn’t inquired with Claude about interfacing the OpenSSL_jll library for curve addition and multiplication. This led to the generation of 200 lines of Julia code, which I could execute in the REPL to explore the entire problem space [3]. These pieces were essential to get competitive performance for the ShuffleProofs package [4], where benchmark figures were also asked to be made by Claude with `Luxor`, which is instead a low-level library lovely in itself.
I would be unable to accomplish those improvements alone and would be highly reluctant to learn what a bignum limb is. It would be nearly impossible to implement those optimisations in such a short time while retaining the big picture of the ecosystem I maintain. I also used to have good experiences with ChatGPT at the beginning, but it silently became more dogmatic and lazy over time and somehow lost its ability to apply analogies between `C`, `Java` or `python` ecosystems.
To use LLMs effectively, one needs to interact with them appropriately and be aware of the biases one makes in the questions. Knowing when to make a gentle nudge and when to contradict is a vital skill to have there to get good answers.
[1]: https://github.com/PeaceFounder/CryptoGroups.jl/blob/0f6b4e2...
[2]: https://github.com/PeaceFounder/CryptoGroups.jl/blob/0f6b4e2...
First release of Go was 2009.
It still isn't practical if you read more code than you write, unless you also use a LLM to summarize the code for you.
Between golang and rust, chatgpt has much easier time with golang.
The standard toolchain (as opposed to python packaging) makes it easier for LLM to debug and run commands. So it's easier to develop a golang based app over python using poetry or uv.
But even if you disagree, S3 is conceptually super simple: put binary blobs, get binary blobs, delete binary blobs. I trust the blobs to be there when I need them. I don't have to think about storage size at all, maybe not even backups (depending on use case).
I still have to worry about network, but that isn't really that much different from disk access that can fail.
So yeah, I think S3 counts as boring. :)
Which is same point that the original post "choose boring technology" makes. I don't see the contradiction.
On the other hand, this could be the same slippery slope that starts at "choose a boring project because it has mature tooling" but ends at "IDE's are a language smell". If the language is so boring that you can't focus on it without an LLM doing the menial work, that could be because there is too much menial work to start with.
Do you run LLMs locally? I'd be keen to have an overview of your stack.
In the article, I mostly mean working with LLMs inside the applications I'm building, as opposed to as a tool as part of development. But I do both.
Right now, I'm trying out Zed, which supports multiple LLMs natively. Just today, I tried Zed + Ollama + Qwen 2.5 Coder 32B running locally, and it worked! Blows my mind that I can have GPT-4o-level assistance running on my laptop. :D
How do you gauge "GPT-4o-level assistance"? Have you tried side-by-side comparisons?
But if that's what you're productive in, I'd say, absolutely!
I'm doing what you're talking about 100%. I've found that established and popular FOSS web software that has normal people users and their support forums, plural, for their normal users (as any popular software has) - this type of "established and non-sexy probably used for office work software" is fully known and understood by LLMs. It's very simple to put a support AI Agent inside the interface to that software, and because the LLM has both the user support forums and the source code itself in the training, that AI Agent can do things against the software's API and data structures by request - it knows them!
Yeah, "boring software" is no longer boring when it can be integrated with characters that know that software as good as the lead developer who wrote it and have the knowledge of a dozen PhDs too.
I'm glad the approach works for you as well! :D It's fascinating to watch a statistical document completion model be able to do so much.
Did anyone try working with LLMs and Swift for example? Is the AI suggesting deprecated libraries from earlier iOS versions / generally having trouble? Or is it working fine?
I suspect that the productivity gain we see now from LLM will generate adequate tech debt in time if people with less experience(or patience) continue to build things with auto generated code without own research and learning.
(Edit: punctuations and disamguify)
The issue doesn't seem to be going away soon though - i expect this actually to put pressure on a lot of projects to have more stable APIs (good and bad, i suppose)
Choose boring technology aka pick the technologies I think are the best.
I think it’s similar to why a lot of places use Ruby on Rails, Django and the likes. They work, and they work well. It’s why people use Debian. It’s to lead relatively uneventful lives as far as the underlying tech goes, which is “boring”.
In my experience you’ll find far less attachment to specific technologies in this crowd of people. They like their stable tools but they won’t preach to you about a specific tool, more so about how choosing something that is simple to work with because it just works is nice. We do it in practice, we use C and we didn’t go onboard with Rust. We use a little Zig but only when it’s completely interoperable with C. In 5-10 years when Rust or Zig are more mature (and boring) we may pick them up again. Well I probably won’t be here by then but I’m sure you know what I mean. Until they get boring, however, we’re just going to use C. I don’t think C is better than Rust and I don’t think you should necessarily copy us, but for us C is “boring” and Rust isn’t.