Deploy PureScript to Europe β Type-Safe Compile-to-JS on EU Infrastructure in 2026
JavaScript is the runtime of the web. It is also a runtime that will let you call a function that does not exist, access a property on undefined, and silently coerce a number to a string in a comparison. These are not edge cases β they are the default behaviour of the language, and they produce bugs that are impossible to catch at compile time because JavaScript has no compile-time type checking unless you add it.
PureScript adds it. Not as an optional annotation layer, not as a gradual type system that allows escape hatches β as a strict, Haskell-derived type system that must typecheck completely before any JavaScript is generated. The output is clean, readable JavaScript. The input is a language where the compiler rejects entire categories of bugs before they can reach production.
PureScript was created by Phil Freeman π¬π§ in 2013 as a personal project and released as open source. Freeman was working at a British consultancy when he wrote the initial compiler β a Haskell developer who wanted the same type safety in the browser that Haskell gave him on the server. PureScript is now a mature language with a rich ecosystem, a dedicated European community, and production use in applications where correctness is not optional.
PureScript applications run on sota.io with full GDPR compliance on EU infrastructure. This guide shows how.
The European PureScript Community
PureScript is deeply rooted in European functional programming research and practice.
Phil Freeman π¬π§ β the creator of PureScript β is British. He built the original compiler in Haskell, published it on GitHub in 2013, and maintained it through the early years of the language's development while working in the UK. The language's design reflects the British functional programming tradition: principled type theory, explicit effects, no implicit global state.
Harry Garrood π¬π§ β based in Edinburgh, Scotland β built and maintains Pursuit (pursuit.purescript.org), the documentation search engine for PureScript packages. Pursuit indexes every published PureScript library, provides type-search capabilities, and is the primary reference tool for the PureScript ecosystem. Building and maintaining Pursuit has made Garrood one of the most influential contributors to PureScript's developer experience. Edinburgh's functional programming tradition β shaped by Simon Peyton Jones and the Haskell research group β runs directly through PureScript's type class system.
Christoph Hegemann π©πͺ β a German software engineer β built psc-ide, the original language server tooling for PureScript IDE integration. psc-ide provided go-to-definition, type information, and autocomplete for PureScript in editors before the Language Server Protocol was standard. The project later evolved into purescript-language-server, which is the basis for PureScript support in VS Code, Emacs, Neovim, and other editors today. German contributions to PureScript's developer tooling made the language accessible to developers who need IDE support.
Philip Wadler π΄σ §σ ’σ ³σ £σ ΄σ ₯ (Edinburgh) and Simon Peyton Jones π΄σ §σ ’σ ³σ £σ ΄σ ₯ (Cambridge/Microsoft Research Cambridge) β authors of the Wadler-Blott paper that introduced type classes to Haskell β are the intellectual ancestors of PureScript's type class system. Every PureScript class, instance, and type class derivation traces directly to the 1989 paper written at the University of Glasgow. PureScript inherits Haskell's type class mechanism and extends it: PureScript type classes are stricter, more principled, and more predictable than their Haskell equivalents.
EU functional programming conferences β Lambda Days (KrakΓ³w π΅π±), BobKonf (Berlin π©πͺ), BOB (Berlin), Clojure/north, and the UK's LambdaConf satellite events β have featured PureScript talks and workshops consistently since 2015. The EU FP community has been a production ground for PureScript adoption, particularly in organisations that use Haskell on the backend and want the same type discipline on the frontend.
Row polymorphism and extensible records β PureScript's most distinctive type-system feature β reflect ongoing type theory research in European computer science. Row types, pioneered by researchers at INRIA France and further developed at universities in the Netherlands and UK, allow PureScript's type checker to track the exact set of fields in a record and verify at compile time that field access is always valid. This is not possible in TypeScript (which uses structural subtyping with potential unsoundness) and is unique among compile-to-JavaScript languages.
Why PureScript for EU Applications
Strict type safety for regulated data. GDPR requires precise control over what personal data is stored, processed, and transmitted. PureScript's type system makes it possible to encode data classification in types β a PersonalData a wrapper that requires explicit handling before the underlying value is accessible. TypeScript's type system has escape hatches (any, as, !). PureScript's does not.
No runtime exceptions from pure code. In PureScript, all effects β HTTP requests, database queries, file reads β are explicit in the type signature. A function that returns Int cannot perform IO. A function that returns Aff Error Int is an asynchronous computation that can fail with Error. The compiler enforces this separation. You cannot accidentally introduce a side effect in a pure function because the type system prevents it.
Effect system for controlled side effects. PureScript uses two effect types: Effect for synchronous effects (DOM manipulation, mutable state) and Aff for asynchronous effects (HTTP, database). Both are explicit in function signatures. This means a code reviewer can see at the type level which functions interact with the outside world β without reading the function body. For EU compliance audits, this is directly useful: data-handling functions are marked as such in their types.
Row polymorphism for safe data transformation. EU data processing pipelines frequently need to transform records β adding fields, removing fields, projecting a subset of fields. PureScript's row types track this precisely. A function that removes a personalEmail field from a record has a type that proves the output does not contain personalEmail. TypeScript cannot express this guarantee; PureScript can.
Compiles to readable JavaScript. PureScript does not compile to optimised opaque JavaScript. It compiles to clean, module-based JavaScript that can be inspected, debugged in browser dev tools, and audited by developers who do not know PureScript. For organisations that need to audit their frontend code for compliance, PureScript output is more auditable than many minification and tree-shaking pipelines.
httpurple: HTTP Servers in PureScript
PureScript on the server runs via httpurple β a PureScript HTTP framework that compiles to Node.js and provides a type-safe routing layer. httpurple allows you to define HTTP routes as pure functions from typed requests to typed responses, with all effects tracked in the type system.
module Main where
import Prelude
import HTTPurple
main :: ServerM
main = serve { port: 8080 } router
where
router { path: ["health"] } = ok "OK"
router { path: ["api", "users"], method: Get } = ok "[]"
router _ = notFound
The entire server is a pure function from request to response. Effects are tracked. Routes are exhaustive β if you add a new route, the compiler verifies the handler is correct. If you access a field that does not exist on the request, the build fails.
For a full application with database access:
module Main where
import Prelude
import HTTPurple
import Effect.Aff (Aff)
import Data.Either (Either(..))
type User = { id :: Int, name :: String, email :: String }
getUsers :: Aff (Array User)
getUsers = do
-- database query via pg-purescript or similar
pure []
main :: ServerM
main = serve { port: 8080 } \req -> case req.path of
["api", "users"] -> do
users <- getUsers
okJson users
_ -> notFound
The Aff type makes the asynchronous, effectful nature of the database query explicit at the type level. getUsers cannot be called from a pure context without a compiler error.
Deploying PureScript on sota.io
PureScript compiles to JavaScript modules. The compiled output runs on Node.js. Deployment follows the same container workflow as any Node.js application.
Step 1 β Compile to JavaScript:
spago build
spago bundle-app --main Main --to output/index.js
spago is the PureScript package manager and build tool. bundle-app produces a single bundled JavaScript file from the compiled PureScript modules.
Step 2 β Write a Dockerfile:
FROM node:22-alpine AS builder
WORKDIR /app
RUN npm install -g purescript spago
COPY spago.yaml spago.lock ./
COPY packages.dhall ./
RUN spago install
COPY src/ src/
RUN spago bundle-app --main Main --to output/index.js
FROM node:22-alpine
WORKDIR /app
COPY --from=builder /app/output/index.js ./index.js
EXPOSE 8080
CMD ["node", "index.js"]
The multi-stage build separates the PureScript compiler toolchain from the runtime image. The final image is a minimal Node.js Alpine container with only the compiled JavaScript.
Step 3 β Deploy to sota.io:
sota deploy
The CLI packages the Dockerfile, sends it to sota.io's EU infrastructure (Frankfurt region, German data centres), builds the image, and starts the container. PostgreSQL is provisioned automatically if you use sota postgres add. No Kubernetes configuration. No cloud provider account. No IAM role to configure.
Your PureScript application runs in Europe, under GDPR jurisdiction, with managed TLS, automatic restarts, and German data centre infrastructure β from a single command.
PureScript vs. TypeScript for EU Applications
PureScript is not a TypeScript replacement for every use case. It is a better choice for specific classes of EU applications.
| Property | PureScript | TypeScript |
|---|---|---|
| Type soundness | Complete β no unsound escapes | Partial β any, as, ! escape hatches |
| Null safety | Structural β Maybe a is the only nullable type | Via strictNullChecks but ! operator escapes it |
| Effect tracking | Type-level β Effect/Aff required | None β any function can have any effect |
| Row polymorphism | Full β extensible records with precise types | Partial β structural subtyping with limitations |
| Runtime exceptions | None from pure code | Any function can throw |
| Learning curve | High β Haskell familiarity helps | Low β JavaScript developers adopt quickly |
| Ecosystem size | Smaller β focused on correctness-first libraries | Very large β entire npm ecosystem |
For EU GDPR compliance code, data transformation pipelines, financial calculation logic, and form validation in regulated contexts β PureScript's guarantees are worth the learning investment. For teams that need to ship quickly and can accept TypeScript's soundness trade-offs, TypeScript is the pragmatic choice.
Production PureScript on EU Infrastructure
Companies and projects using PureScript in production tend to be in domains where correctness is non-negotiable:
Financial services. PureScript's sum types make it natural to represent financial states exhaustively. A payment status is either Pending, Confirmed, Failed String, or Refunded β and the compiler forces you to handle every case. UK and Irish fintech firms have used PureScript for their calculation engines where a missed case in a TypeScript switch would be a silent bug.
Healthcare data processing. EU MDR (Medical Device Regulation) requires software validation. PureScript's effect types allow formal reasoning about which functions access patient data β a useful property for documenting regulatory compliance.
Public sector. Several Dutch and German government IT contractors have used PureScript for administrative software where auditability and correctness outweigh development speed. The compiled JavaScript output is auditable without knowledge of PureScript.
Distributed ledger applications. Cardano β the blockchain protocol β uses PureScript for its frontend tooling and wallet interfaces. Cardano has significant European developer presence (IOHK has offices in the EU) and its use of PureScript as a production language has raised awareness of the language in the EU tech community.
The sota.io Advantage for PureScript Teams
GDPR by default. Your PureScript application's data β all the typed, validated, effect-tracked data you process β lives on German servers, under EU law. You do not need to configure cross-border transfer rules. You do not need Standard Contractual Clauses for your own infrastructure. The data stays in Europe because the infrastructure is in Europe.
Managed PostgreSQL. PureScript backends commonly use PostgreSQL for persistence. sota.io provisions managed PostgreSQL instances in the same EU data centre as your application, with automated backups and connection pooling. You connect with a single environment variable. No RDS console. No cross-region latency.
Fast cold starts. PureScript compiles to efficient JavaScript modules. On Node.js, startup time is measured in milliseconds. sota.io's EU containers start your application in under a second β consistent with the latency requirements of European users who expect sub-100ms response times.
No vendor lock-in. PureScript produces standard JavaScript. If you leave sota.io, your compiled application runs on any Node.js host. You are not locked into a PureScript-specific runtime or deployment model.
Getting Started
# Install PureScript tooling
npm install -g purescript spago
# Create new project
mkdir my-purescript-app && cd my-purescript-app
spago init
# Add httpurple for HTTP server
spago install httpurple
# Build
spago build
# Install sota CLI
npm install -g sota-cli
# Deploy to EU
sota deploy
PureScript on sota.io gives you the strictest type system available in the compile-to-JavaScript ecosystem, running on EU infrastructure with full GDPR compliance. Phil Freeman built PureScript because he wanted Haskell's guarantees in the browser. sota.io gives you Haskell's guarantees in the browser β and a deploy target that keeps your users' data in Europe.
Deploy PureScript to Europe in minutes. Sign up for sota.io β EU-native PaaS, GDPR-compliant by default, managed PostgreSQL, zero DevOps.