A couple million lines of Haskell: Production engineering at Mercury
A fintech bank’s claim to run “a couple million lines” of production Haskell has prompted debate over whether the language meaningfully drives its reliability and pace of change, or whether success mainly reflects strong engineering culture. Commenters highlight benefits such as expressive types, fewer bugs, and a self-selecting pool of highly motivated developers, while also noting real drawbacks: slow builds, a small ecosystem, rigid type-heavy designs, and the risk of hiring people who optimize for language cleverness over business value. Comparisons with Rust, TypeScript, Erlang, and mainstream OO languages center on trade-offs between safety, debuggability, performance, and long-term maintainability in large, mission-critical systems.
Perceived impact of Haskell on Mercury’s success
- Several commenters think choosing Haskell early was a non‑trivial factor in Mercury’s reliability, especially through events like rapid growth and the SVB crisis.
- Others argue we can’t know how much is due to Haskell vs. overall good engineering management; language choice and culture are tightly coupled.
Hiring, culture, and talent pool
- Using Haskell shrinks the candidate pool but is seen as a strong filter for motivated, “serious” engineers.
- Some companies prefer generalists who learn Haskell on the job over long‑time Haskell specialists who may be more interested in language “noodling” than shipping.
- There’s concern about “tool fetishism”: people who treat Haskell (or any favorite tech) as a hammer looking for nails.
Types, FP, and correctness vs. flexibility
- Many highlight strong types and “encode invariants in types” as Haskell’s biggest production advantage, especially for security and domain rules (e.g., modeling sanitized vs. raw data, login/auth states).
- Similar patterns are said to work in Rust, TypeScript, OCaml, C++, C#, etc., but with more boilerplate and weaker guarantees in dynamic languages.
- Debate over option types (
Maybe) vs. nullable union types: option types prevent null pointer bugs but make some API changes noisy; unions can ease evolution but depend heavily on discipline. - Some warn about “types as business spec”: modeling everything in types can make policy changes high‑friction and codebases rigid.
Comparisons to Rust, TypeScript, and others
- Rust is praised for similar type‑level guarantees but criticized as verbose and hard to refactor, especially with async and higher‑order patterns; some find themselves more productive in Rust, others far less.
- TypeScript can approximate Haskell patterns (e.g., branded/newtypes), but the incantations are fragile and easy to misuse.
- OCaml, F#, Clojure, Erlang/Elixir, and others appear as alternatives with different trade‑offs (GC, “let it crash” philosophy, better variants, easier modularity).
Tooling, cross‑compilation, and ecosystem
- Haskell’s build tooling, cross‑compilation, static linking, and Docker workflows are described as slow and painful compared to Go.
- Limited libraries and the need to re‑implement observable, instrumentable clients are seen as both a cost and a long‑term reliability win.
Debugging, observability, and scale
- Some find debugging FP harder because state is abstracted away; others say purity makes reasoning and testing easier.
- The article’s emphasis on “design for introspection” resonates: building in tracing, metrics, and testability is viewed as essential for large Haskell systems.
User experiences with Mercury as a product
- Multiple users report years of positive experience with Mercury’s banking products: smooth UX, reliable wires, powerful APIs, virtual cards, and granular account organization.
- Some say Mercury feels “several standard deviations” above typical banks; lack of features like Zelle is a noted drawback.