# Using Haskell in production

**URL:** <https://discourse.haskell.org/t/using-haskell-in-production/12932>\
**Category:** Links\
**Created:** [September 9, 2025, 6:16pm UTC](https://discourse.haskell.org/t/using-haskell-in-production/12932 "2025-09-09T18:16:32Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![lorenzo](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/lorenzo/32/1294_2.png) [@lorenzo](https://discourse.haskell.org/u/lorenzo)\
**Post date:** [September 9, 2025, 6:16pm UTC](https://discourse.haskell.org/t/using-haskell-in-production/12932/1 "2025-09-09T18:16:32Z")

</div>

I didn’t write this, but I found it a balanced view on the pros and cons of using Haskell in production: [https://agentultra.com/blog/using-haskell-in-production/](https://agentultra.com/blog/using-haskell-in-production/)

I wonder if others share the same view that Haskell is lacking in runtime introspection tool, and what would you say it is missing.

---

<div class="post-metadata">

**Author:** ![Vlix](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/vlix/32/1551_2.png) [@Vlix](https://discourse.haskell.org/u/Vlix)\
**Post date:** [September 9, 2025, 8:03pm UTC](https://discourse.haskell.org/t/using-haskell-in-production/12932/2 "2025-09-09T20:03:23Z")

</div>

In my experience, the performance tooling is the biggest “gap” for Haskell in Production.

For anything else, I have only ever gotten frustrated making changes to large projects written in other languages. Refactoring in Haskell, IMHO, is the biggest win. Adding features and changing requirements with Haskell is often a breeze, where as in JavaScript or Python I would second guess almost every change I try to make because there’s zero guarantees (though TypeScript has helped a bit there) and I’m just there hoping we have enough tests (and the right ones) to catch anything that I might break while changing code.

---

<div class="post-metadata">

**Author:** ![Ambrose](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/ambrose/32/5672_2.png) [@Ambrose](https://discourse.haskell.org/u/Ambrose)\
**Post date:** [September 9, 2025, 8:19pm UTC](https://discourse.haskell.org/t/using-haskell-in-production/12932/3 "2025-09-09T20:19:42Z")

</div>

Every other “better” production language [1] I’ve had a chance to use in prod lacks a repl and therefore results in bad code tho. It becomes a pain to truly write small modular code so instead you write black boxes that do a lot and integration test their behavior.

So I confidently say those languages have bad tooling 🙂

[1] Golang, Java, Rust. Dynamic langs have repls but the code is always automagic framework soup and hard to hold in your hand.

---

<div class="post-metadata">

**Author:** ![Yuras](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/yuras/32/5296_2.png) [@Yuras](https://discourse.haskell.org/u/Yuras)\
**Post date:** [September 10, 2025, 9:00am UTC](https://discourse.haskell.org/t/using-haskell-in-production/12932/4 "2025-09-10T09:00:55Z")

</div>

> It has excellent support for the `STM` library, async exceptions, resource management and is a delight to use.

There are two types of haskellers - who absolutely love async exceptions, and who absolutely hate them. I wonder why.

---

<div class="post-metadata">

**Author:** ![lorenzo](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/lorenzo/32/1294_2.png) [@lorenzo](https://discourse.haskell.org/u/lorenzo)\
**Post date:** [September 10, 2025, 2:29pm UTC](https://discourse.haskell.org/t/using-haskell-in-production/12932/5 "2025-09-10T14:29:59Z")

</div>

I’m on the “async exceptions are great, actually” camp

---

<div class="post-metadata">

**Author:** ![LaurentRDC](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/laurentrdc/32/4950_2.png) [@LaurentRDC](https://discourse.haskell.org/u/LaurentRDC)\
**Post date:** [September 10, 2025, 4:48pm UTC](https://discourse.haskell.org/t/using-haskell-in-production/12932/6 "2025-09-10T16:48:53Z")

</div>

I’d love to read about this.

I’m learning about async exceptions by writing a Cloud Haskell backend based on QUIC, and I’m getting a little frustrated.

---

<div class="post-metadata">

**Author:** ![Yuras](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/yuras/32/5296_2.png) [@Yuras](https://discourse.haskell.org/u/Yuras)\
**Post date:** [September 10, 2025, 5:06pm UTC](https://discourse.haskell.org/t/using-haskell-in-production/12932/7 "2025-09-10T17:06:38Z")

</div>

> [@lorenzo](#):
>
> I’m on the “async exceptions are great, actually” camp

Same here. For me STM and async exceptions are the killer features of Haskell. But there are too many people who hate async exceptions (or exceptions in general) to brush it off. I mean, there has to be something about it.

---

<div class="post-metadata">

**Author:** ![Yuras](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/yuras/32/5296_2.png) [@Yuras](https://discourse.haskell.org/u/Yuras)\
**Post date:** [September 10, 2025, 5:15pm UTC](https://discourse.haskell.org/t/using-haskell-in-production/12932/8 "2025-09-10T17:15:09Z")

</div>

> [@LaurentRDC](#):
>
> ’m getting a little frustrated.

It’s hard to say anything specific without particular cases, but for me the point of no returns was when I figured that most bugs related to handling async exceptions are not specific to async exceptions, and are just general exception handling bugs. And most exception handling bugs are just error handling bugs.

I.e. if you are mishandling async exceptions, there is a high change you are mishandling sync exceptions as well. It’s just that async exceptions trigger the bug more often.

Sorry if it doesn’t help 🙂

---

<div class="post-metadata">

**Author:** ![lorenzo](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/lorenzo/32/1294_2.png) [@lorenzo](https://discourse.haskell.org/u/lorenzo)\
**Post date:** [September 10, 2025, 5:31pm UTC](https://discourse.haskell.org/t/using-haskell-in-production/12932/9 "2025-09-10T17:31:44Z")

</div>

I formed this opinion after having to deal with golang for a few years at work. In go, the only pattern at your disposal to deal with situations that would be trivially solved with an asynchronous exception is to use event polling.

The basic idea is that you have a “rendez-vous” point in your application logic where you check for certain conditions, like “ctrl-c”, or “should stop now”. The problem with this approach is that it is not composable. You need to create [as many “rendez-vous”](https://golangbot.com/context-timeout-cancellation/) as places in your code you would wish to abort execution. In practice, developers don’t want to do this because it makes the code less readable, and forces them to think about this problem everywhere. What ends up happening is that programs tend to have large blocking chunks of logic. You cannot escape from those blocks until they finish, which could be a very long time, or never.

If you ever had to do ctrl-c while running “terraform apply” only to wait a really long time to realize it will not stop, you know what I’m talking about.

That was a source of bugs in my company. Things got stuck more often than we wanted to. The only solution was to thread context structs and check for cancellation in individual threads or tasks. I’m not saying it was impossible to fix, it was just very inconvenient and took a long time to get right.

With Haskell the solution seems too magical. You just have to get the exception handling right once, and then it works for everything: timeouts, allocation limits, ctrl-c, thread racing…

Simon Marlow wrote about this more eloquently that I’m able to: [Asynchronous Exceptions in Practice · Simon Marlow](https://simonmar.github.io/posts/2017-01-24-asynchronous-exceptions.html)

---

<div class="post-metadata">

**Author:** ![LaurentRDC](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/laurentrdc/32/4950_2.png) [@LaurentRDC](https://discourse.haskell.org/u/LaurentRDC)\
**Post date:** [September 10, 2025, 6:03pm UTC](https://discourse.haskell.org/t/using-haskell-in-production/12932/10 "2025-09-10T18:03:14Z")

</div>

> [@Yuras](#):
>
> I.e. if you are mishandling async exceptions,

I guess I was asking indirectly: how does one use async exceptions effectively?

Another post linked to [https://simonmar.github.io/posts/2017-01-24-asynchronous-exceptions.html](https://simonmar.github.io/posts/2017-01-24-asynchronous-exceptions.html). I’ll have a look at that!

---

<div class="post-metadata">

**Author:** ![Yuras](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/yuras/32/5296_2.png) [@Yuras](https://discourse.haskell.org/u/Yuras)\
**Post date:** [September 10, 2025, 6:17pm UTC](https://discourse.haskell.org/t/using-haskell-in-production/12932/11 "2025-09-10T18:17:06Z")

</div>

> [@LaurentRDC](#):
>
> I guess I was asking indirectly: how does one use async exceptions effectively?

Sorry for being too dense, but I’m not sure I understand the question. Note: English is not my native language, so it’s possible I’m misreading your comment.

I can only offer a quote from the Simon’s post mentioned above:

```haskell
In the vast majority of our Haskell codebase we don’t need to worry about them at all.

```

That matches my experience as well. You don’t usually use async exceptions at all. You don’t even worry about them most of the time. But you use `System.Timeout.timeout`, `Control.Concurrent.Async.race` etc which internally rely on async exceptions.

I’d be happy to answer a specific question, like “how to use async exceptions is this particular situations” though.

---

<div class="post-metadata">

**Author:** ![LaurentRDC](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/laurentrdc/32/4950_2.png) [@LaurentRDC](https://discourse.haskell.org/u/LaurentRDC)\
**Post date:** [September 10, 2025, 6:22pm UTC](https://discourse.haskell.org/t/using-haskell-in-production/12932/12 "2025-09-10T18:22:16Z")

</div>

Thanks! I don’t have a concrete question at this time. I will educate myself first.

To get back to the topic : I concur that STM is amazing when using Haskell in production

---

<div class="post-metadata">

**Author:** ![Ambrose](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/ambrose/32/5672_2.png) [@Ambrose](https://discourse.haskell.org/u/Ambrose)\
**Post date:** [September 10, 2025, 7:19pm UTC](https://discourse.haskell.org/t/using-haskell-in-production/12932/13 "2025-09-10T19:19:14Z")

</div>

Ever use Go? And leak goroutines? That’ll take down your entire server fleet.

And to avoid it you have to remember to use idioms to make sure they don’t leak - impossible to `bracket` or otherwise abstract?

That’ll make you appreciate the existence of async exceptions. I think the hate for them is due to the loudest Haskellers being library authors, where async exceptions are added complexity and potential footguns.

---

<div class="post-metadata">

**Author:** ![chreekat](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/chreekat/32/2669_2.png) [@chreekat](https://discourse.haskell.org/u/chreekat)\
**Post date:** [September 12, 2025, 7:51am UTC](https://discourse.haskell.org/t/using-haskell-in-production/12932/14 "2025-09-12T07:51:48Z")

</div>

> [@Vlix](#):
>
> In my experience, the performance tooling is the biggest “gap” for Haskell in Production.

Increasingly, this gap is only in the lack of knowledge about tools that have been developed the past few years! [https://youtu.be/8i8HJiBI0lo?si=KRj2zSVjqKpm-Asx&t=1082](https://youtu.be/8i8HJiBI0lo?si=KRj2zSVjqKpm-Asx&t=1082) is a funny example of this.

I think this video is one of the most important ones about Haskell performance tooling anyone could watch right now. I recommend people watch it beginning to end. It shows how far we’ve come and what’s currently available.

---

<div class="post-metadata">

**Author:** ![Vlix](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/vlix/32/1551_2.png) [@Vlix](https://discourse.haskell.org/u/Vlix)\
**Post date:** [September 12, 2025, 10:04pm UTC](https://discourse.haskell.org/t/using-haskell-in-production/12932/15 "2025-09-12T22:04:48Z")

</div>

Ah, yes. I still have to watch that one. Was excited to see it in my feed. 🙏

---

<div class="post-metadata">

**Author:** ![vem](https://avatars.discourse-cdn.com/v4/letter/v/a698b9/32.png) [@vem](https://discourse.haskell.org/u/vem)\
**Post date:** [September 14, 2025, 4:25pm UTC](https://discourse.haskell.org/t/using-haskell-in-production/12932/16 "2025-09-14T16:25:15Z")

</div>

> the performance tooling is the biggest “gap” for Haskell in Production

IME it’s better than Rust (heap profiling and flamegraphs). It helps to know about `cabal build –enable-profiling` and [ghc-prof-flamegraph](https://hackage.haskell.org/package/ghc-prof-flamegraph)

But maybe there’s some cool stuff out there I don’t know about in C++ etc.
