2026-04-12·6 min read·sota.io team

Deploy Haskell & Servant to Europe — EU Hosting for Haskell APIs in 2026

Haskell is not a mainstream language — and that is precisely the point. Teams that choose Haskell are making a deliberate bet: they would rather spend time reasoning about types than chasing runtime errors in production. When you deploy a Haskell API that compiles, you have a reasonable expectation that it behaves correctly.

Servant takes this philosophy and applies it directly to REST API design. Your API specification is expressed as a Haskell type. The compiler verifies that your handlers satisfy the spec. If you rename a field, change a response type, or remove an endpoint, the code stops compiling until every part of the codebase agrees. This is a qualitatively different development experience from writing OpenAPI YAML and hoping your implementation matches.

This guide covers deploying a Haskell/Servant API to European infrastructure using sota.io — the EU-native PaaS with German data residency by default.

Why European Fintech Runs on Haskell

Haskell has an outsized presence in European financial services. Standard Chartered Bank runs its derivatives pricing platform on Haskell. Jane Street (London office) has contributed extensively to the GHC compiler and runs trading systems in OCaml and Haskell. Barclays Capital used Haskell for risk modeling. Deutsche Bank has internal Haskell tooling for financial product modeling.

The reasons are structural, not historical:

Correctness over convenience. Financial calculations must be right. A misplaced integer overflow, an unhandled edge case in portfolio rebalancing, a null reference in a trade confirmation — these cause real financial losses. Haskell's type system catches entire categories of bugs at compile time that dynamically typed languages find at 3 AM in production.

Pure functions and referential transparency. Haskell enforces a strict separation between pure computations (no side effects) and effectful code (I/O, database, network). This makes financial logic — price calculations, risk models, fee structures — easy to test, reason about, and audit. A pure function with the same inputs always produces the same output. Auditors like this property.

Strong algebraic types for domain modeling. newtype OrderId = OrderId UUID and newtype TradeId = TradeId UUID are different types in Haskell. You cannot accidentally pass a trade ID where an order ID is expected. For complex financial domains with dozens of ID types and constrained numeric ranges, this prevents entire classes of logic errors.

GDPR and EU data residency. London Fintech teams serving EU clients post-Brexit face a clear data residency requirement: personal financial data of EU residents must stay in the EU. Running Haskell APIs on sota.io satisfies this requirement without infrastructure complexity.

The Servant Framework

Servant is a type-level DSL for describing REST APIs. An API definition in Servant looks like this:

type API =
       "users" :> Get '[JSON] [User]
  :<|> "users" :> ReqBody '[JSON] CreateUser :> Post '[JSON] User
  :<|> "users" :> Capture "id" UserId :> Get '[JSON] User
  :<|> "users" :> Capture "id" UserId :> DeleteNoContent

This is a Haskell type, not a string or a config file. The compiler knows every endpoint, every request body type, every response type. If you implement a handler that returns the wrong type, you get a compile error — not a 500 at runtime.

Handler derivation. From the API type, Servant derives the expected type signature for each handler. The compiler enforces that your implementation matches. There is no room for a handler that returns User when the API says it should return [User].

Client generation. The same API type generates a type-safe Haskell HTTP client. You write the API type once, and Servant gives you both a server and a client that are guaranteed to agree on the wire format.

Documentation. servant-swagger and servant-openapi3 derive OpenAPI 3.0 documentation directly from the same API type. Your docs are always in sync with your implementation — not because of tooling or discipline, but because they are computed from the same source of truth.

What You Need

Writing a Haskell/Servant API

A minimal Servant application:

-- src/Main.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}

module Main where

import Data.Text (Text)
import Network.Wai.Handler.Warp (run)
import Servant

type API =
       "health" :> Get '[JSON] Text
  :<|> "items"  :> Get '[JSON] [Item]
  :<|> "items"  :> ReqBody '[JSON] CreateItem :> Post '[JSON] Item

data Item = Item
  { itemId   :: Int
  , itemName :: Text
  } deriving (Generic, ToJSON, FromJSON)

data CreateItem = CreateItem
  { createItemName :: Text
  } deriving (Generic, ToJSON, FromJSON)

server :: Server API
server = healthHandler :<|> getItemsHandler :<|> createItemHandler

healthHandler :: Handler Text
healthHandler = return "ok"

getItemsHandler :: Handler [Item]
getItemsHandler = return [Item 1 "example"]

createItemHandler :: CreateItem -> Handler Item
createItemHandler body = return $ Item 42 (createItemName body)

main :: IO ()
main = do
  let port = 8080
  putStrLn $ "Starting server on port " <> show port
  run port (serve (Proxy @API) server)

The cabal file:

-- servant-api.cabal
cabal-version:   3.0
name:            servant-api
version:         0.1.0

executable servant-api
  main-is:            Main.hs
  hs-source-dirs:     src
  build-depends:
      base          ^>=4.18
    , servant-server ^>=0.20
    , warp           ^>=3.3
    , aeson          ^>=2.2
    , text           ^>=2.0
  default-language:   Haskell2010
  ghc-options:        -O2 -Wall

Dockerfile for sota.io

GHC compilation is memory-intensive. The multi-stage build produces a small final image — the compiled Haskell binary plus its runtime dependencies:

# Stage 1: Build
FROM haskell:9.6-slim AS builder

WORKDIR /build

# Copy dependency files first for layer caching
COPY servant-api.cabal cabal.project* ./
RUN cabal update && cabal build --only-dependencies

# Copy source and build
COPY src/ ./src/
RUN cabal build && \
    cp $(cabal list-bin servant-api) /build/server

# Stage 2: Runtime
FROM debian:bookworm-slim

RUN apt-get update && apt-get install -y \
    libgmp10 \
    ca-certificates \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY --from=builder /build/server .

EXPOSE 8080
CMD ["./server"]

What this produces: The GHC-compiled binary links against libgmp (big integer support, required by GHC's runtime) and the standard C library. The final image is typically 30–60 MB — significantly smaller than a JVM-based equivalent at 200–400 MB.

Step 1: Deploy to sota.io

npm install -g @sota-io/cli
sota deploy

First build takes 8–15 minutes — GHC compilation is the slowest of any language on this list, but the result is a native binary with no runtime overhead. Subsequent deploys cache the dependency build layer, reducing rebuild time to 2–3 minutes for source-only changes.

Connecting to PostgreSQL

Persistent is the standard Haskell ORM, with explicit schema definitions and type-safe queries:

share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
  Item
    name Text
    createdAt UTCTime default=now()
    deriving Show
|]

runMigration migrateAll  -- run schema migrations at startup

sota.io automatically injects DATABASE_URL as an environment variable when a PostgreSQL database is provisioned for your project. Read it with System.Environment.getEnv "DATABASE_URL".

Performance: Haskell vs Other Languages

GHC-compiled Haskell runs as native machine code. It is competitive with Go and Rust on throughput for CPU-bound workloads, and Servant's lightweight routing adds minimal overhead:

RuntimeCold StartMemory (idle)Throughput (req/s)
Haskell / Servant~100ms~25 MBVery high
Go / Gin~20ms~15 MBVery high
Rust / Axum~15ms~10 MBHighest
Java / Spring Boot3–10s200–400 MBHigh
Node.js / Fastify~100ms~50 MBHigh
Python / FastAPI~300ms~80 MBModerate

Haskell's lazy evaluation model means memory usage is more variable than Rust or Go for some workloads — profile with +RTS -s for production-critical services. For typical REST APIs serving JSON, the default configuration is efficient.

EU Compliance for Haskell/Fintech

Deploying on sota.io gives you:

RequirementStatus
GDPR Article 28 DPAAvailable on request
EU data residency (Germany)Default — no configuration
No US Cloud Act jurisdictionYes — German entity, no US parent
ISO 27001 infrastructureHetzner Frankfurt
No vendor lock-inStandard Docker containers

For FCA-regulated firms in London with EU clients, for BaFin-regulated operations in Germany, and for fintech teams in the Nordics serving EU consumers under DSGVO, these properties are not optional — they are requirements before any data flows to production.

DACH & Nordics Verticals for Haskell

London/Nordics Fintech. The Haskell community in European financial services is concentrated in London (post-Brexit still serving EU clients under GDPR), Stockholm, and Amsterdam. Teams building trading infrastructure, risk models, or pricing engines in Haskell have an existing culture of correctness-first engineering. sota.io fits this culture: EU data residency by default, no configuration surprises.

Insurance (Actuarial). Complex actuarial models — life tables, reinsurance pricing, claims reserves — are a natural fit for pure functional programming. Several German insurance companies use Haskell or F# internally. The audit trail for pure functions is straightforward.

Banking (Formal Verification). GHC's type system can encode invariants that would require separate specification tools in other languages. Teams building BaFin-compliant payment infrastructure value compile-time guarantees over runtime monitoring.

Comparison: sota.io vs Other Platforms for Haskell

Featuresota.ioHerokuRailwayFly.io
Default regionGermany (EU)US defaultUS defaultConfigurable
EU data residencyYesNeeds configPaid planYes (select)
GDPR EU DPAYes (EU entity)No (Salesforce)No (US)Limited
Haskell supportYes (Docker)Yes (Buildpacks)Yes (Docker)Yes (Docker)
Managed PostgreSQLIncludedPaid add-onPaid add-onSeparate
PricingFlat €9/moUsage-basedUsage-based USDUsage-based USD

On build times: GHC compilation is slower than any other language on this list. All platforms have this challenge. sota.io caches dependency layers aggressively — initial builds are slow, subsequent deploys are fast.

Getting Started

  1. Write your Servant API type definition
  2. Implement handlers — the compiler tells you if anything is missing
  3. Add the Dockerfile above
  4. sota deploy

Your Haskell API runs in Germany, with EU data residency, HTTPS, and managed PostgreSQL — all included.


This guide is part of the Deploy to Europe series → covering 21 programming languages. Last updated: April 2026.

See Also