Deploy OCaml to Europe — EU Hosting for OCaml & Dream Framework in 2026
OCaml is not a language you stumble into. You choose it deliberately — because you need a type system that eliminates runtime errors before they happen, because you are building a trading system where a mismatched type costs real money, or because your team has read Jane Street's engineering blog and takes the "make illegal states unrepresentable" principle seriously.
The language has deep European roots. OCaml was developed at INRIA — Institut National de Recherche en Informatique et en Automatique — in France, one of Europe's premier computer science research institutions. It is, in a very literal sense, an EU-native language. And yet most deployment guides point at US-based infrastructure. That changes here.
This guide shows how to deploy OCaml applications — specifically using the Dream framework — to European infrastructure using sota.io, with EU data residency by default.
Why OCaml for Production Backends
Jane Street is the most visible example of OCaml in production: the firm processes hundreds of billions of dollars in trades daily on OCaml infrastructure. But the reasons they chose OCaml are not proprietary to high-frequency trading:
Algebraic data types and exhaustive pattern matching. When you model a financial instrument, a payment state, or an API response as an OCaml variant type, the compiler forces you to handle every case. There is no "default" branch that silently swallows edge cases. This property is valuable for any domain where unhandled states represent bugs rather than minor annoyances.
No runtime type errors. OCaml's type inference eliminates an entire class of production failures. You cannot call a function with the wrong argument type at runtime — the program simply does not compile. In domains like EU financial services, where regulatory compliance and auditability are mandatory, this is not academic: it is a risk management property.
OCaml 5 Multicore and effect handlers. OCaml 5 finally removed the Global Interpreter Lock (GIL) that limited OCaml to single-core parallelism. The new runtime supports true multicore execution via a work-stealing scheduler, and introduces effect handlers — a structured approach to concurrency that is more composable than callbacks and more lightweight than async/await state machines. For backend services under load, OCaml 5 is a fundamentally different beast than OCaml 4.
Native compilation. OCaml compiles to native machine code via its own backend (not LLVM). The resulting binaries are fast, small, and have predictable latency characteristics — important for services where tail latency matters.
EU FinTech adoption. Beyond Jane Street, OCaml has a strong presence in European quantitative finance. Teams at Swiss and Austrian FinTech firms, derivatives desks, and research-oriented financial institutions use OCaml for pricing engines, risk models, and execution infrastructure. INRIA's ongoing research — including the Coq/Rocq proof assistant, which is written in OCaml — keeps the ecosystem academically and industrially active in France and across the EU.
Dream: Modern Web Development in OCaml
The server-side OCaml ecosystem historically meant Ocsigen (powerful but complex), CoHTTP (low-level), or Httpaf (fast but minimal). Dream changes this picture.
Dream is a modern web framework for OCaml — inspired by the ergonomics of Express (Node.js) and the type-safety of OCaml. It uses Lwt (Lightweight Threads) for cooperative concurrency and has a clean, composable middleware model. For teams familiar with functional web frameworks like Haskell's Scotty or F#'s Giraffe, Dream will feel immediately natural.
Key features:
- Type-safe routing with middleware composition
- WebSocket support built-in
- Session management and CSRF protection
- Server-sent events for real-time push
- Full TLS support
- Templates via Embedded ML (EML — OCaml embedded in HTML, similar to ERB)
Dream is actively maintained and represents the current best practice for OCaml web development. The older Apache-based mod_ocaml stack is not covered here — it belongs to a different era.
What You Need
- OCaml 5.x (or 4.14+ for OCaml 4 multicore)
- opam (OCaml Package Manager)
- Dream and its dependencies in your
dune-project - A
Dockerfile(we will write one below)
Step 1: A Minimal Dream Application
A production-ready Dream app has this structure:
my-api/
├── bin/
│ ├── main.ml
│ └── dune
├── lib/
│ ├── routes.ml
│ └── dune
├── dune-project
└── .ocamlformat
A minimal bin/main.ml:
let () =
let port =
match Sys.getenv_opt "PORT" with
| Some p -> int_of_string p
| None -> 8080
in
Dream.run ~interface:"0.0.0.0" ~port
@@ Dream.logger
@@ Dream.router [
Dream.get "/health" (fun _ ->
Dream.json {|{"status": "ok"}|}
);
Dream.get "/api/users/:id" (fun request ->
let id = Dream.param request "id" in
Dream.json (Printf.sprintf {|{"id": "%s"}|} id)
);
]
The dune-project and bin/dune:
; dune-project
(lang dune 3.0)
(name my-api)
; bin/dune
(executable
(name main)
(libraries dream))
Step 2: Write a Production Dockerfile
OCaml builds with opam and dune. The multi-stage pattern keeps the runtime image small — the opam toolchain is large but only needed at build time:
# Build stage — OCaml 5 + opam on Ubuntu
FROM ocaml/opam:ubuntu-22.04-ocaml-5.1 AS build
# Switch to root for apt, then back to opam user
USER root
RUN apt-get update && apt-get install -y \
pkg-config \
libssl-dev \
libev-dev \
&& rm -rf /var/lib/apt/lists/*
USER opam
WORKDIR /app
# Copy opam files first for layer caching
COPY --chown=opam my-api.opam ./
RUN opam install --deps-only --yes .
# Copy source
COPY --chown=opam . .
# Build release binary
RUN opam exec -- dune build --release bin/main.exe
# Runtime stage — minimal Debian image
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y \
libssl3 \
libev4 \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=build /app/_build/default/bin/main.exe ./server
EXPOSE 8080
ENTRYPOINT ["./server"]
The runtime image is typically 60–100 MB. The opam toolchain (several GB) stays in the build stage only.
Step 3: Deploy to sota.io
# Install the sota CLI
npm install -g sota-cli
# Login
sota login
# Deploy from your project root
sota deploy
# Your app is live at https://your-app.sota.run
sota.io detects the Dockerfile, builds it on German infrastructure, and serves your application with automatic TLS. No Kubernetes configuration, no nginx setup, no SSL certificate management.
Step 4: PostgreSQL with Caqti and Ppx_rapper
For database access, the OCaml ecosystem offers Caqti (type-safe database driver abstraction) paired with Ppx_rapper (compile-time SQL query validation). Together they give you a level of database type-safety that is unusually strong — SQL queries are checked against your PostgreSQL schema at compile time.
When you attach a managed PostgreSQL instance in sota.io, the DATABASE_URL environment variable is injected automatically.
(* lib/db.ml *)
let database_url =
match Sys.getenv_opt "DATABASE_URL" with
| Some url -> url
| None -> "postgresql://localhost:5432/mydb"
let pool =
match Caqti_lwt_unix.connect_pool (Uri.of_string database_url) with
| Ok pool -> pool
| Error err ->
failwith (Caqti_error.show err)
(* Type-safe query using ppx_rapper *)
let find_user id =
[%rapper
get_opt
{sql| SELECT @int{id}, @string{email} FROM users WHERE id = %int{id} |sql}
]
|> Caqti_lwt.Pool.use pool
With ppx_rapper, the SQL is parsed at compile time. If the column name or type does not match, your project does not build. This eliminates an entire category of production bugs that dynamically-typed ORMs cannot catch.
Add to bin/dune:
(executable
(name main)
(libraries dream caqti-lwt caqti-driver-postgresql ppx_rapper))
Step 5: Configure sota.toml
[app]
name = "my-ocaml-api"
region = "eu-central" # Frankfurt, Germany
[build]
dockerfile = "Dockerfile"
[env]
PORT = "8080"
# DATABASE_URL is injected automatically when you attach a PostgreSQL service
Performance: OCaml 5 vs Other Backends
OCaml 5's multicore runtime produces competitive results for backend workloads:
| Runtime | Requests/sec (simple JSON) | Memory (baseline) | Latency p99 |
|---|---|---|---|
| Rust/Axum | ~95,000 | ~8 MB | ~1.2 ms |
| Go/Chi | ~82,000 | ~15 MB | ~1.8 ms |
| OCaml 5/Dream | ~68,000 | ~22 MB | ~2.1 ms |
| .NET/ASP.NET Core | ~65,000 | ~55 MB | ~2.4 ms |
| Java/Spring Boot | ~48,000 | ~180 MB | ~3.2 ms |
| Node.js/Express | ~32,000 | ~45 MB | ~4.8 ms |
OCaml 5 is genuinely fast. The numbers above are for a simple JSON endpoint under concurrent load — OCaml's native compilation and the new multicore scheduler put it solidly in the top tier. For comparison: Python/FastAPI peaks around 8,000–12,000 req/sec on the same workload.
More importantly, OCaml's performance characteristics are predictable. There is no JVM warm-up period, no garbage collector that pauses for hundreds of milliseconds, and no GIL contention. For financial services applications where tail latency matters — where the 99th percentile matters as much as the mean — this predictability is a feature.
EU Deployment: Why It Matters for OCaml Teams
OCaml's primary production user base is concentrated in finance, research, and regulated industries — all sectors where EU data residency is not optional:
Swiss and Austrian FinTech. FINMA (Swiss Financial Market Supervisory Authority) and the Austrian FMA have explicit guidelines on data localization for supervised financial institutions. An OCaml trading or risk system needs to run on EU-jurisdiction infrastructure to meet these requirements. US-headquartered PaaS providers — even those with EU regions — remain subject to the US Cloud Act: a US government request can compel data disclosure regardless of physical data location.
INRIA and academic research. European research institutions that build on OCaml — at INRIA, ETH Zurich, Sorbonne, and elsewhere — often need to keep research data on EU-controlled infrastructure for funding compliance, IP protection, or simply because their data involves human subjects under GDPR.
EU-funded projects. Horizon Europe grants frequently have data sovereignty requirements. Academic OCaml backends serving research tools need an EU-native deployment target.
sota.io is German-incorporated, runs on Hetzner Frankfurt infrastructure, and has no US corporate parent. The Schrems II implications that affect AWS, GCP, Azure, Vercel, and Railway do not apply.
sota.io vs the Alternatives for OCaml
| Feature | sota.io | Fly.io | Railway | Render | Heroku |
|---|---|---|---|---|---|
| EU data residency (default) | Yes — Germany | Partial | No | No | No |
| German legal entity | Yes | No | No | No | No |
| US Cloud Act exposure | None | Yes | Yes | Yes | Yes |
| Managed PostgreSQL included | Yes | Add-on | Add-on | Add-on | Add-on |
| OCaml/opam Docker support | Full | Full | Full | Full | Limited |
| Flat-rate pricing | Yes | Usage-based | Usage-based | Usage-based | Usage-based |
| DPA (GDPR Article 28) | Yes | Limited | No | Limited | Limited |
Fly.io has good OCaml support and EU regions, but is a US company subject to Cloud Act jurisdiction. Railway has no EU-specific data residency story. Heroku (Salesforce) has limited Docker support and no EU-native option.
For OCaml teams in regulated EU industries, sota.io is the only PaaS that covers both the technical requirement (Docker-based OCaml deployment) and the compliance requirement (EU data residency, DPA, no Cloud Act exposure) in one product.
DACH and EU FinTech Verticals
Quant Finance (Zurich, Vienna, Frankfurt). Teams building derivatives pricing engines, risk calculation services, or market-making infrastructure in OCaml will find that sota.io's flat-rate pricing and managed PostgreSQL cover the standard deployment pattern: a stateless computation service + a PostgreSQL database for position and trade data. The compliance properties matter: FINMA-regulated entities in Switzerland cannot use Cloud Act-exposed providers.
EU Research Institutes. OCaml backends serving research tools — data pipelines, formal verification services, type-checking APIs — need EU-controlled infrastructure for GDPR compliance. INRIA-adjacent projects in particular have a natural fit with an EU-native PaaS, given the language's origin.
Jane Street-influenced startups. A growing cohort of European fintech startups have adopted OCaml influenced by Jane Street's open-source tooling (Core, Async, Base, ppx_sexp_conv). These teams value correctness and type safety, tend to deploy conservative, well-reasoned infrastructure, and have compliance requirements that rule out US-headquartered providers.
Getting Started
# Install opam if you haven't
bash -s -- < (curl -fsSL https://opam.ocaml.org/install.sh)
# Create a new OCaml 5 switch
opam switch create 5.1.0
# Install Dream
opam install dream
# Create a minimal project
mkdir my-ocaml-api && cd my-ocaml-api
# ... (add dune-project, bin/main.ml, Dockerfile as above)
# Deploy to EU
sota deploy
Your OCaml backend is live in Germany, with automatic HTTPS, managed PostgreSQL available on request, and a flat monthly rate — no usage surprises, no Cloud Act exposure.
OCaml is a language where the compiler tells you when you are wrong before your users do. Your deployment infrastructure should give you the same confidence about compliance. sota.io does.
Deploy your OCaml application to EU infrastructure today — sign up for early access or run sota deploy if you already have an account.