After 7 years in production, Scarf has reluctantly moved away from Haskell
Avi Press | July 10, 2026
—
Disclaimer This has been a hard post to write. I almost didn't write it at all, since I prefer to build and promote than to critique. However, I hope this post can add constructively to the discussion about Haskell’s future. I must underline that I'm not writing this criticizing Haskell from the outside. I care enough about Haskell to be honest about why Scarf has reluctantly moved away from it, in hopes it sways people in the community to take this feedback seriously.
Where I've been For the last 16 years, I have been a huge fan of Haskell. It has been undeniably the most important programming language in my life. Learning it made me a much better programmer. I have advocated for it, built a company that runs on it, and I serve on the board of the Haskell Foundation and the Haskell.org committee. I have also been open about the places where I think Haskell needs to improve. Since Scarf launched, our backend has been built in Haskell. The main API that powers our app uses libraries like Servant, Beam on top of PostgreSQL. We also built a high-performance Haskell service for Scarf Gateway directly on top of WAI, which sits directly in the download path for a high volume of open source package traffic. These systems have real uptime requirements, contractually committed SLAs, and we have managed that successfully in production for years. We put Haskell through a serious production test, and many of its promises held up. The code was reliable. The type system caught real bugs. The language forced us to be thoughtful about how we modelled our domain. High performance code has been generally straight-forward to achieve. But the costs were real too. The biggest ones were compilation time and ecosystem friction. We spent a lot of time optimizing builds, caches, Nix, developer environments, CI, and all the other machinery you end up needing around a serious Haskell codebase. For a long time, that was workable. Our team knows the language and tooling deeply. We knew where the sharp edges were, and we mostly lived with it. Then AI changed the tradeoffs.
Haskell after AI LLMs are now very good at writing code. They are not perfect, obviously, but they are good enough that the economics of software development have changed. Historically, I thought about errors as something you caught in one of two places: at compile time or at runtime. Now there is a third place: code generation time. The model can often avoid the mistake before the compiler ever sees the code. And as the models get better, the relative value of catching every possible issue at compile time changes. This is not to say type safety has become worthless. But the cost of typechecking matters much more now. If an LLM can produce a working implementation in a few minutes, but your compile step takes dramatically longer, then your language and build system have become a bottleneck in the development loop. The important metric: how long does your entire development feedback cycle take, and what portion of that time is spent waiting on your compiler? If a human spends an hour writing some code, a long compile cycle is annoying but may be tolerable. If an agent can draft a plausible change in minutes and then spends even 15 minutes waiting for the project to build from a cold start, the compiler has now moved from being a papercut to being the dominant cost of that thread of work. This becomes unbearable when you start using many coding agents in parallel. If you are working on one thing at a time, maybe you pay the cold build cost once and then keep going. But increasingly, that is not how I want to work. I want to spin up multiple worktrees, fork off different lines of work, let agents try things, review the results, and keep the useful ones. In that world, cold start time matters a lot. If every new worktree needs a long Haskell build, or needs careful cache setup, or burns a ton of memory, then every new thread of work starts with a tax. If I want five agents exploring five branches in parallel, that tax multiplies. People in Haskell talk a lot about caching, Nix, remote builders, and similar tools. Those tools help. We used them. But caching is never perfect, and the amount of effort required to make it feel good enough is itself part of the problem. In practice, parallel AI-assisted development wants cheap, disposable execution contexts. I want to be able to say: fork this off, try the change, run the tests, show me what happened. Our Haskell environment was not cheap enough for that style of work. If everything is cached and you make a small change, you can often get a very fast compile. Sometimes the loop is 20 seconds and that feels great. But that is the best case, and the best case is not what you can optimize the whole system around. The deeper your change goes into core parts of the build plan, the less that story holds. In an agent-heavy workflow, you end up caring a lot more about the cold-start case, the average case, and the deeper-change case. The amount of engineering effort required to make the perfect-cache case happen reliably is itself part of the tax. That became more and more painful.
How we moved At Scarf, we started doing all new API work in Python. We deployed a Python API server alongside the Haskell one, routed requests to the right place, and began moving functionality over as we touched it. New API routes go into Python, existing Haskell code keeps running, and over time the new server becomes the main path and our Haskell footprint will shrink. That approach let us move without the risk of a dramatic cutover. It also meant we had to reimplement some core things: authentication, database access, shared models, deployment images, tests, and operational glue. Historically, that kind of setup work would have felt expensive. With LLMs, it wasn’t bad, porting existing code to a new language is quite straightforward for today’s models. The time we got back in our development cycle, from waiting and wrestling with the toolchain has now been reallocated to shipping more features with more comprehensive testing. AI is good at writing a lot of tests. You still have to watch it, because it can absolutely write garbage and fake tests, but the loop is fast enough that this tradeoff works much better than I would have expected a few years ago. The result is hard to capture in a single metric. PR throughput did not obviously go up. Commit volume is noisy. Lines of code is a bad proxy. Deployment count is muddy because it includes previews, infrastructure, and other noise. But the productivity change is visible in the shape of what we can now ship with high effort, with minimal oversight, and even what we can ship fully automatically. From customer call -> ticket filed -> PR opened -> PR reviewed and iterated -> merged -> deployed, we can sometimes have bug fixes live before I get off the call with a customer. Resisting this kind of productivity is not an option anymore. So far, we haven’t lost much in the switch. The type safety we gave up hasn’t been noticeable in any concrete way yet, especially considering our test coverage has never been better. Now when bugs do make it out, we can hotfix them at a pace I’ve never experienced before; fixes are literally one slack message away now. Our engineering team is more energized by the productivity gains and a completely new frontier of technology to wield. We are spending significantly less time thinking about the developer toolchain that we had to in the past.
The Haskell ecosystem problem Haskell is in real danger. AI is here to stay. The people and ecosystems that use it well are going to move much faster than the people and ecosystems that do not. I do not think this is subtle anymore. A skilled AI-powered engineer can now do work in days that used to take weeks or months. I also want to be clear about where I am saying this from. I am not outside the Haskell world throwing rocks at it. I am directly involved with language leadership via my role(s) in HF. I do have some ability to help, and I will continue to help where I can. At the same time, my spare time is greatly limited by the reality of running Scarf. I’m trying to not stand idly by, but I certainly am limited in my own ability to unilaterally change these dynamics. There are plenty of people in the Haskell world who also see the same shift in economics, and who want Haskell to move faster to adapt to them. But net-net, the progress of the Haskell toolchain and ecosystem is not where I think it needs to be. And yet, when AI comes up in Haskell spaces, the conversation often seems more focused on restriction than enablement. I understand why people have concerns. There should be norms. There should be disclosure. It is reasonable to ask people to say when code was AI-assisted, what models were involved, and how it was reviewed. But there is a strong cohort in the camp of "do not use LLMs," or even "we do not want to support workflows that involve LLMs," which I believe is the wrong side of history. I predict it will prove bad for the language’s ecosystem. An AI-enabled Haskell ecosystem would ask different questions. How do we make Haskell easier for agents to use well? How do we get more high-quality Haskell examples into model training data? How can we scale reviews? How do we make library docs full of copy-pastable, realistic examples, not just beautiful types? How do we make project bootstrap fast? How do we make error messages more agent-friendly? How do we reduce cold build times? How do we make common industrial patterns obvious to a model that is trying to help? Haskell should be unusually well positioned to be relevant to AI-enabled engineers and agents. Type safety can be a huge advantage for LLM-generated code if the compiler is helping the agent converge quickly. But that is not the same thing as optimizing the language for humans writing code by hand. Agents have different bottlenecks. They are cheap at generating code and expensive when blocked. They benefit from fast feedback, clear examples, low setup friction, and errors that help them repair the code quickly. If Haskell wants to be great in the AI era, it needs to optimize for that world on purpose.