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
- GHC 9.6+ (Glasgow Haskell Compiler)
- Cabal or Stack for dependency management
- A
Dockerfile(we will write one below) - A sota.io account
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:
| Runtime | Cold Start | Memory (idle) | Throughput (req/s) |
|---|---|---|---|
| Haskell / Servant | ~100ms | ~25 MB | Very high |
| Go / Gin | ~20ms | ~15 MB | Very high |
| Rust / Axum | ~15ms | ~10 MB | Highest |
| Java / Spring Boot | 3–10s | 200–400 MB | High |
| Node.js / Fastify | ~100ms | ~50 MB | High |
| Python / FastAPI | ~300ms | ~80 MB | Moderate |
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:
| Requirement | Status |
|---|---|
| GDPR Article 28 DPA | Available on request |
| EU data residency (Germany) | Default — no configuration |
| No US Cloud Act jurisdiction | Yes — German entity, no US parent |
| ISO 27001 infrastructure | Hetzner Frankfurt |
| No vendor lock-in | Standard 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
| Feature | sota.io | Heroku | Railway | Fly.io |
|---|---|---|---|---|
| Default region | Germany (EU) | US default | US default | Configurable |
| EU data residency | Yes | Needs config | Paid plan | Yes (select) |
| GDPR EU DPA | Yes (EU entity) | No (Salesforce) | No (US) | Limited |
| Haskell support | Yes (Docker) | Yes (Buildpacks) | Yes (Docker) | Yes (Docker) |
| Managed PostgreSQL | Included | Paid add-on | Paid add-on | Separate |
| Pricing | Flat €9/mo | Usage-based | Usage-based USD | Usage-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
- Write your Servant API type definition
- Implement handlers — the compiler tells you if anything is missing
- Add the
Dockerfileabove 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
- Deploy Concurrent Haskell to Europe → — Simon Peyton Jones (Glasgow), Software Transactional Memory (STM 2001); composable concurrency for Haskell backends
- Deploy Miranda to Europe → — David Turner (Kent), direct ancestor of Haskell; lazy evaluation and algebraic types
- Deploy Clean to Europe → — Nijmegen lazy functional language influenced by Miranda; shares Haskell's evaluation model