Haskell in Production
Prerequisites: Cabal and Stack projects
This lesson collects the practices teams use to build, ship, and run Haskell software.
Build settings
common shared
default-language: GHC2021
ghc-options: -Wall -Wcompat -Wincomplete-record-updates
-Wredundant-constraints -Wmissing-deriving-strategies
executable server
import: shared
ghc-options: -O2 -threaded -rtsopts "-with-rtsopts=-N -T"
- Treat warnings as errors in CI (
--ghc-options=-Werror), but not in local development. -threadedand-Nlet the runtime use all cores;-Tmakes runtime statistics available to metrics libraries.- Pin dependencies with
cabal freezeor a Stackage snapshot, and commit the freeze file so every build uses the same versions.
Shipping
- A compiled Haskell program is a single native executable — copy
it to the server, no runtime to install.
cabal list-bin serverprints where it was built. - Docker: build in a large image with GHC, then copy the binary into
a small runtime image (multi-stage build). Fully static Linux binaries
can be built with GHC on Alpine (musl) and
--enable-executable-static. - Nix is popular in the Haskell community for fully reproducible builds and development environments.
Guarding against the unexpected
import System.Timeout (timeout)
import Control.Exception
import Text.Read (readMaybe)
slowComputation :: IO Integer
slowComputation = evaluate (sum [1 ..])
main :: IO ()
main = do
r1 <- timeout 100000 (evaluate (sum [1 .. 1000 :: Integer]))
print r1
r2 <- timeout 100000 slowComputation
print r2
print (readMaybe "12; DROP TABLE users" :: Maybe Int)
r3 <- try (evaluate (1 `div` (0 :: Int))) :: IO (Either ArithException Int)
print r3
Just 500500
Nothing
Nothing
Left divide by zero
timeout microseconds actionreturnsNothingif the action takes too long — even the infinitesum [1 ..]is interrupted safely.- Parse untrusted input into precise types (
readMaybe, aeson, a parser) and reject everything else. - Catch exceptions at the boundary of each request or job, log them, and
keep serving —
async, Warp, and most job libraries do this for you. - Limit memory with
+RTS -M512mso a runaway computation fails cleanly instead of taking down the machine.
Code quality tools
- HLint for suggestions, Ormolu/Fourmolu for formatting — both usually run in CI.
- weeder finds unused code; stan does static analysis for common pitfalls such as partial functions.
- HLS in every developer's editor.
cabal outdatedlists dependencies with newer versions.
Where Haskell is used
Haskell's strengths — correctness, refactoring safety, concurrency, and expressive types — make it popular for compilers and developer tools (Pandoc, ShellCheck, the Elm compiler), financial systems and trading, blockchain (Cardano), back-end APIs, and anywhere complex business rules must be modeled precisely.
What's next
You've completed the course. Try the Advanced Projects — an interpreter, a JSON API, and a concurrent crawler — and then read What You Should Know Now — and What's Next for where to go from here.