The Future of Software Engineering

What would software engineering be like if we didn't have to care about friction? This is the question we have to ask in the age of AI. Developer experience is now mitigated through AI. We only have to care about whether the agents can understand what we are doing.

Does this open us up to new modalities of development that were rejected? Many technologies were, strictly, better in some ways. But they were not used because they were too difficult and cumbersome. In the last 15 years, especially, developer experience has been the main thing we cared about: Is this maintainable?

I chatted with my friend at a coding AI startup the other day who said that pre AI he never would have chosen Rust to build apps in. Yes, maybe you would choose it for the few things that really need it. But by and large the overhead is simply too big for most things. I'm sure Jarred from Bun would tell you the same.

This same pattern will emerge in other areas too.

In early 2016 I went to a conference in Brooklyn. I had to look up the name, because I didn't remember. It was called Compose. If you want a real flashback, the conference was sponsored by Jet. I remember their talk, it was largely about how they picked F# because they wanted to be the place that had the coolest tech you could have if you worked on Windows. An interesting strategy, it did seem to work out pretty well for them overall. (I used to buy a lot of discount stuff on Jet!)

A few of the talks there were on Unikernels. They were a then pretty interesting idea. It is a program that is statically linked to the kernel itself. The program is compiled in (or perhaps shipped in with) just the libraries and kernel modules it needs. Do you need glibc? No? It's not gonna be there. Do you need kernel level networking? No? It's not gonna be there either.

Try it: only the imported files exist. The program looks for /etc/shadow, and grix reports it wasn't imported.

You didn't have to accept that the chunky monolithic-kerneled Linux needed to have SMB and webcam drivers loaded in every program you were making. They also seemed tailor made for the container age. You could build out a container that just had a small handful of things on it.

They lost to containers, though. More limited Linux distros won because they were easier to use. Unikernels required too much of a developer. And, while they had some security promises, it's hard to justify that they were so much more secure than Linux. Linux is the most battle tested technology in history.

There are a bunch of reasons why they lost out. But the main reason why is that kubernetes and docker simply offered too much. Now we're in a brand new age. AI has made it so much easier to run a unikernel. This is the kind of thing that might happen when friction goes to zero. And why not build out a very limited container from a unikernel, instead of running the unikernel directly on the hypervisor (as people imagined you'd do in 2013)?

I decided to try to build a unikernel.

Why build one? I'm between jobs briefly, I start my new job Monday, so I don't have a real use for one yet. So instead of trying to find a contrived application for one, I'd prefer to build one. Also, I always kinda wanted to build a toy OS, and this seemed like a fun time to do that.

What do you need to do to build a unikernel? What features does it need?

It needs all the features of an OS. Multitasking, networking, forking, threads.

Try it: the shell can't fork until you grant process.

It has to be able to run programs that the OS can run. I specifically chose to give it Linux compatibility, to ensure that you (or I) wouldn't have to fool around with compile targets. Unmodified programs can run on my kernel, though some will fail as not everything is currently supported.

Try it: Alpine's Python 3.12, unmodified, in a terminal. Downloads 15 MB the first time.

I decided not to statically link the program to the kernel, instead it compiles to a more limited kernel and allows you to run your program on top of that. It gives it more freedom (you don't need to write rust, you can run anything on it.)

Limited Sandbox

I built my unikernel as an agent sandbox. It's meant for your agent to run in and execute code safely, and without having to deal with the overhead of modern sandboxed environments. The security is in part built in.

Try it: the socket is denied, and grix says which capability would allow it. Tick net and run it again.

Because there's less going on, there's also significantly less overhead. That means that you can get away with a smaller footprint in your sandboxed environments. You don't have to just accept that your Claude will need room to stretch out. He can fit just fine in just the ram he needs, without the OS overhead.

Try it: bash and busybox in a terminal. Try echo hi > /tmp/x without fs_write.

I was going to put in a few code examples here, but I realized they aren't necessary. You aren't going to be writing the code anyway. So, instead, I've sprinkled a few demos of this through this. These aren't running on a server. I have compiled QEMU to WASM and the kernel is running on that in your browser.

This is the future we're looking at. We need to rethink the fundamentals we have taken for granted. These choices got us through the last 15 years of SaaS hypergrowth. But we don't need to accept these choices anymore. They are limiting us. And we can do much better.