2026-06-23ยท9 min readยทsota.io team

Deploy Racket to Europe โ€” Matthias Felleisen's Language-Oriented PaaS in 2026

In 1990, Matthias Felleisen arrived at Rice University in Houston with a problem. He had spent years studying programming languages at Indiana University โ€” formal semantics, lambda calculi, continuation-passing style โ€” and he had a theory. The theory was that programming languages were not merely tools. They were media. The language you wrote in shaped what you could think, what you could build, and how you could teach it.

Felleisen had been born and raised in Karlsruhe, Germany โ€” a city that would later become the Karlsruhe Institute of Technology, one of Germany's nine elite TU9 universities. His early education was in the German Gymnasium tradition: rigorous, systematic, oriented toward deep understanding rather than rote application. He studied at KIT before emigrating to pursue a PhD in the United States, where he would spend his career at Rice, Northwestern, and Northeastern โ€” building a research group that would change how the world teaches programming.

The project he started at Rice with Robby Findler, Matthew Flatt, and Shriram Krishnamurthi was called PLT โ€” Programming Languages Team. Their first artefact was PLT Scheme, a Scheme dialect with a pedagogical mission: write a language powerful enough for research, clean enough for students, and extensible enough to become any language you needed. In 2010, PLT Scheme was renamed Racket. The name change signalled something: Racket was no longer trying to be Scheme. It had become its own thing.

Racket is a language-oriented programming language. That is not marketing language. It means that Racket's primary value proposition is the ability to create new languages โ€” domain-specific languages, pedagogical languages, research languages โ€” that compile down to Racket, share Racket's tooling, and run on Racket's runtime. Racket doesn't just support macros. It supports language levels: the #lang declaration at the top of every Racket file specifies which language that file is written in. #lang racket is the full language. #lang htdp/bsl is the beginner teaching language. #lang typed/racket is the gradually-typed variant. #lang scribble/doc is the documentation language that generates the Racket documentation you read online.

This is a profound idea. It means that a Racket codebase can contain files written in different languages โ€” each optimised for its domain โ€” that all interoperate because they ultimately compile to the same thing. No other mainstream language system works this way.

The European Roots of Racket

Felleisen's German origin is not a footnote. The PLT research programme โ€” which produced Racket, DrRacket, the How to Design Programs (HtDP) curriculum, and a generation of programming language researchers โ€” reflects the European tradition of treating programming as a discipline of formal reasoning rather than applied engineering.

Matthias Felleisen ๐Ÿ‡ฉ๐Ÿ‡ช (born Karlsruhe, Germany) studied at what is now the Karlsruhe Institute of Technology (KIT ๐Ÿ‡ฉ๐Ÿ‡ช) before completing his PhD at Indiana University under Daniel Friedman. His academic lineage runs through the American tradition of Scheme and lambda calculus research, but the foundational rigour โ€” the insistence on formal semantics, on reduction rules, on syntactic proofs of correctness โ€” belongs to the European school. Felleisen has supervised over 25 PhD students, many of whom went on to lead language research at US and European universities.

Shriram Krishnamurthi ๐Ÿ‡ฎ๐Ÿ‡ณ (Brown University) co-founded PLT and co-authored How to Design Programs (HtDP), the free textbook that teaches beginning programming through Racket. HtDP is used in introductory CS courses at dozens of European universities โ€” its influence on EU computer science education is direct and ongoing.

European university adoption is the strongest signal. DrRacket and the HtDP curriculum are standard in introductory CS courses at:

This is not coincidental. The How to Design Programs approach โ€” systematic function design, type-driven development, test-first specification โ€” maps naturally onto the European engineering tradition. EU universities that take programming education seriously tend to converge on Racket.

Eugen Kohlbecker ๐Ÿ‡ฉ๐Ÿ‡ช (Indiana University, later Germany) deserves special mention. While not a PLT member, Kohlbecker's 1986 paper "Hygienic Macro Expansion" โ€” which solved the variable capture problem in Lisp macros and gave the world hygienic macros โ€” is the theoretical foundation of Racket's macro system. Without Kohlbecker's insight, Racket's language-oriented programming model would be impossible. Racket's syntax-rules, syntax-case, and define-syntax all build on the hygiene Kohlbecker proved.

What Racket Brings to Modern Backends

Racket has a built-in, production-capable HTTP server in its standard library. This is not a third-party dependency โ€” it ships with the language. The web-server package supports servlets, continuations, and both synchronous and asynchronous request handling.

Racket's built-in web server:

#lang racket/base
(require web-server/servlet
         web-server/servlet-env)

(define (start request)
  (response/xexpr
   `(html
     (head (title "Racket API"))
     (body (p "Hello from Racket on sota.io")))))

(serve/servlet start
               #:port 8080
               #:listen-ip #f
               #:servlet-path "/")

JSON REST API with web-server and json:

#lang racket/base
(require web-server/servlet
         web-server/servlet-env
         web-server/http/response-structs
         json)

(define (api-response data [status 200])
  (response
   status #"OK"
   (current-seconds)
   #"application/json; charset=utf-8"
   '()
   (ฮป (out)
     (write-json data out))))

(define (handle-users request)
  (match (request-method request)
    [#"GET"
     (api-response
      (list (hasheq 'id 1 'email "alice@example.com")
            (hasheq 'id 2 'email "bob@example.com")))]
    [#"POST"
     (let* ([body (request-post-data/raw request)]
            [data (bytes->jsexpr body)])
       (api-response (hasheq 'created #t 'data data) 201))]
    [_ (api-response (hasheq 'error "Method Not Allowed") 405)]))

(define (dispatch request)
  (define path (url->string (request-uri request)))
  (cond
    [(string-prefix? path "/api/users") (handle-users request)]
    [(string=? path "/health")
     (api-response (hasheq 'status "ok"))]
    [else (api-response (hasheq 'error "Not Found") 404)]))

(serve/servlet dispatch
               #:port 8080
               #:listen-ip #f
               #:servlet-regexp #rx"")

PostgreSQL via db library:

#lang racket/base
(require db)

(define conn
  (postgresql-connect
   #:server (getenv "PGHOST")
   #:port (string->number (or (getenv "PGPORT") "5432"))
   #:database (getenv "PGDATABASE")
   #:user (getenv "PGUSER")
   #:password (getenv "PGPASSWORD")))

; Parameterized query โ€” safe from SQL injection
(define (get-user-by-id id)
  (query-maybe-row conn
    "SELECT id, email, created_at FROM users WHERE id = $1"
    id))

(define (create-user! email)
  (query-exec conn
    "INSERT INTO users (email, created_at) VALUES ($1, NOW())"
    email))

; Transactions
(define (transfer-credits! from-id to-id amount)
  (call-with-transaction conn
    (lambda ()
      (query-exec conn
        "UPDATE accounts SET balance = balance - $1 WHERE id = $2"
        amount from-id)
      (query-exec conn
        "UPDATE accounts SET balance = balance + $1 WHERE id = $2"
        amount to-id))))

Racket macros for domain-specific routing DSL:

One of Racket's genuine superpowers is that you can build your own routing syntax without any runtime overhead:

#lang racket/base
(require (for-syntax racket/base syntax/parse)
         web-server/servlet)

; Define a routing macro โ€” this is Racket's language-oriented approach
(define-syntax-rule (route-table [method path handler] ...)
  (lambda (request)
    (define req-method (request-method request))
    (define req-path (url->string (request-uri request)))
    (cond
      [(and (bytes=? req-method method)
            (string=? req-path path))
       (handler request)]
      ...
      [else (response/empty #:code 404)])))

; Usage: clean, declarative, zero runtime cost
(define app
  (route-table
    [#"GET"  "/api/users"   list-users]
    [#"POST" "/api/users"   create-user]
    [#"GET"  "/health"      health-check]))

Typed Racket for production APIs:

#lang typed/racket/base
(require typed/web-server/http)

; Types checked at compile time โ€” no surprises in production
(: make-json-response (-> JSExpr Response))
(define (make-json-response data)
  (response
   200 #"OK"
   (current-seconds)
   #"application/json"
   '()
   (ฮป ([out : Output-Port])
     (write-json data out))))

(: user-id->record (-> Positive-Integer (Option (HashTable Symbol JSExpr))))
(define (user-id->record id)
  (let ([row (query-maybe-row conn
               "SELECT id, email FROM users WHERE id = $1" id)])
    (and row
         (hasheq 'id (vector-ref row 0)
                 'email (vector-ref row 1)))))

Deploying Racket to European Infrastructure

Racket applications deploy as Docker containers. The official Racket Docker image is maintained by the Racket team and available on Docker Hub.

Dockerfile for a Racket web service:

FROM racket/racket:8.14

WORKDIR /app

# Copy project files
COPY *.rkt ./
COPY *.rktd ./

# Compile for faster startup
RUN raco make server.rkt

# Expose port
EXPOSE 8080

CMD ["racket", "server.rkt"]

sota.yaml for sota.io deployment:

name: my-racket-api
build:
  dockerfile: Dockerfile
port: 8080
database:
  type: postgresql
  version: 17
env:
  - PGHOST
  - PGDATABASE
  - PGUSER
  - PGPASSWORD

sota.io injects the PostgreSQL connection details automatically as environment variables. Your Racket service is running in Frankfurt or Amsterdam within minutes, GDPR-compliant by default.

For smaller services, raco pkg compilation on build:

FROM racket/racket:8.14-full

WORKDIR /app
COPY . .

# Install dependencies from info.rkt
RUN raco pkg install --deps search-auto --batch

# Pre-compile everything
RUN raco make main.rkt

EXPOSE 8080
CMD ["racket", "main.rkt"]

Why GDPR Compliance Matters for Racket Teams

Racket's primary deployment context in Europe is research and education โ€” but the compliance requirements in those contexts are strict. EU universities processing student data must comply with GDPR. Research institutions handling personal data in studies must have explicit data processing agreements. INRIA, KIT, TU Delft, and Edinburgh all operate under national and EU data protection frameworks that prohibit processing personal data on US infrastructure without appropriate safeguards (which are increasingly unavailable post-Schrems II).

When you deploy Racket on AWS, GCP, or Azure โ€” even in an EU region โ€” your data is subject to the CLOUD Act, which gives US authorities access to data held by US cloud providers regardless of physical location. For EU universities, EU research institutions, and any team processing personal data of EU citizens, this is not a theoretical risk. It is a compliance violation.

sota.io is incorporated and operated in the EU. No CLOUD Act exposure. No Standard Contractual Clauses needed. Your data stays in EU jurisdiction by design. For the Racket community โ€” which is predominantly European in its academic base โ€” this is the natural deployment target.

The Performance Envelope

Racket's built-in web server performs well for API workloads. It is not the fastest language runtime, but it is significantly faster than the "Lisp is slow" stereotype suggests, and its performance is predictable:

WorkloadRacket (web-server)Node.js (Express)Go (net/http)
JSON REST API~6,000 req/s~12,000 req/s~45,000 req/s
DB-backed CRUD~2,000 req/s~3,500 req/s~12,000 req/s
Static response~15,000 req/s~25,000 req/s~80,000 req/s

For research tools, internal APIs, educational platforms, and services where correctness, macro-driven DSLs, or language-oriented architecture matter more than raw throughput โ€” Racket is the right choice. Its compilation model (raco make) pre-compiles to bytecode, eliminating startup overhead for containerised deployments.

Getting Started

# Install Racket (includes DrRacket IDE)
# Linux/macOS:
curl -sSf https://mirror.racket-lang.org/installers/8.14/racket-8.14-x86_64-linux-cs.sh | sh

# Or via package manager:
# Ubuntu: apt install racket
# macOS: brew install racket

# Verify
racket --version

Minimal web server to get started:

#lang racket/base
(require web-server/servlet-env
         web-server/servlet
         json)

(define (start request)
  (response/full
   200 #"OK"
   (current-seconds)
   #"application/json"
   '()
   (list (jsexpr->bytes (hasheq 'status "running" 'version "1.0")))))

(serve/servlet start
               #:port (string->number (or (getenv "PORT") "8080"))
               #:listen-ip #f
               #:servlet-regexp #rx"")

Deploy to sota.io:

# Create project
sota init my-racket-api

# Deploy
sota deploy

# Your Racket API is live in the EU

The Racket Community and European CS Education

The PLT research group's greatest achievement may not be Racket itself โ€” it may be How to Design Programs (HtDP), the free textbook that teaches programming through systematic design. HtDP treats programming as an intellectual discipline: before writing code, design the data. Before implementing a function, write its signature and purpose statement. Before testing, formulate examples.

This pedagogy has spread across European universities because it produces students who can reason about programs, not just write them. TU Delft adopted HtDP because Dutch computer science education values formal correctness. Edinburgh adopted it because the School of Informatics has always emphasised theory. KTH adopted it because Swedish engineering education prioritises rigour over vocational training.

The result is that Racket has tens of thousands of alumni in the EU who were taught to program using it. Many of them now work at European tech companies, research institutions, and public sector IT departments. The language they write production code in may be Python or Go โ€” but the way they think about programs was shaped by Racket.

For teams at EU institutions deploying Racket today โ€” research backends, educational platforms, computational linguistics tools, formal verification services โ€” sota.io provides the EU-native infrastructure that matches Racket's European intellectual heritage.