Deploy Ada to Europe — EU Hosting for Ada Web Services in 2026
Ada is the programming language that the European aerospace and defence industry trusts with human lives. When an Airbus A380 pilot moves the sidestick, Ada software interprets that input and commands the flight control surfaces. When an Ariane rocket performs a trajectory correction burn, Ada code is running the guidance system. When Paris Métro line 14 — the fully automated line — decides whether to open its doors, Ada is the language executing that safety logic. This did not happen by accident. Ada was designed in Europe, by European engineers, for exactly this purpose.
Jean Ichbiah was a French computer scientist born in 1940 who studied at the École Polytechnique in Paris — the grande école that has produced a disproportionate share of France's technical elite. In the late 1970s, Ichbiah led the team at CII Honeywell Bull, a French computer manufacturer in Paris, that won the US Department of Defense competition to design a new programming language for embedded and real-time systems. The DoD had surveyed its software projects in 1974 and found over 450 different programming languages in use — a fragmentation that made maintenance and interoperability nearly impossible. They wanted one language, designed right, that could handle the demands of safety-critical systems.
Ichbiah's team submitted their design — called Green — in 1977. After two rounds of competition and independent evaluation, Green won. The language was standardized in 1983 as Ada 83, named after Ada Lovelace, and Jean Ichbiah received the ACM Distinguished Paper Award for its design. The language specification was published as an ANSI/ISO standard — a level of formal rigour unusual for programming languages of that era.
Ichbiah returned to France and continued refining the language until his death in 2007. Ada 95 added object-oriented programming. Ada 2005 and Ada 2012 added contracts and interfaces. The current standard, Ada 2022, adds more parallel programming constructs. Through all of it, the language's core commitments — strong typing, deterministic behaviour, explicit concurrency, provable correctness — have remained intact.
AdaCore, headquartered in Paris on the Rue du Faubourg Saint-Honoré, is the company that maintains GNAT — the GNU Ada Translator — which is the primary Ada compiler used worldwide. AdaCore was founded in 1994 and has grown into the central institution of the Ada ecosystem. GNAT Pro is the commercial Ada toolchain used by Airbus, Thales, SNCF, and hundreds of other European safety-critical software teams. The free community edition, GNAT Community Edition, makes Ada accessible for new projects. AdaCore's engineers contribute directly to the GCC Ada front-end, the SPARK formal verification tools, and the Ada Web Server library. Paris did not just invent Ada — Paris still maintains it.
The use of Ada in European infrastructure is not historical. It is present and ongoing. Airbus (Toulouse and Hamburg) uses Ada in the flight control computers of the A380, A350, and A320neo families. The fly-by-wire systems that replaced mechanical linkages between cockpit and control surfaces are Ada programs that execute in hard real-time with microsecond deadlines. Thales (Paris) uses Ada in avionics, railway signalling, and defence systems across the EU. The French Direction Générale de l'Armement specifies Ada for mission-critical defence software. RATP and SNCF use Ada in signalling systems for the Paris Métro and TGV network. The European Space Agency (technical centre in Darmstadt, Germany) has used Ada for spacecraft software since the 1990s — the Automated Transfer Vehicle that supplied the International Space Station was Ada software.
For EU development teams building safety-critical, high-reliability, or long-lifecycle services — industrial control backends, medical device APIs, infrastructure monitoring systems, defence-adjacent data processing — deploying on EU infrastructure is not just a compliance preference. It is often a contractual requirement. This guide shows how to deploy an Ada web service to sota.io.
Ada Web Server — AdaCore's Web Library
The Ada Web Server (AWS) is a production-quality library maintained by AdaCore that provides HTTP, HTTPS, WebSocket, REST API, and template rendering capabilities for Ada applications. Despite sharing initials with Amazon Web Services, AWS predates and has nothing to do with Amazon — it is an Ada library that has been in continuous development since the early 2000s.
For EU teams building REST APIs or data services in Ada, AWS provides:
- A non-blocking HTTP/HTTPS server with SSL support
- Template engine (Tmplt) for server-side rendering
- WebSocket support for real-time applications
- SOAP/XML web services
- Session management
- Static file serving
Building an Ada Web Service
Project Structure
src/
main.adb
api-server.adb
api-server.ads
handlers/
health_handler.adb
health_handler.ads
products_handler.adb
products_handler.ads
ada_web_service.gpr
Dockerfile
sota.yaml
Project File
-- ada_web_service.gpr
with "aws";
with "gnatcoll";
project Ada_Web_Service is
for Source_Dirs use ("src/**");
for Object_Dir use ".obj";
for Exec_Dir use "bin";
for Main use ("main.adb");
package Compiler is
for Default_Switches ("Ada") use
("-g", "-O2", "-gnatwa", "-gnatVa", "-gnato");
end Compiler;
package Linker is
for Linker_Options use ("-lpthread");
end Linker;
end Ada_Web_Service;
HTTP Server Setup
-- src/api-server.ads
package API.Server is
procedure Start (Port : Positive := 8080);
procedure Stop;
end API.Server;
-- src/api-server.adb
with AWS.Server;
with AWS.Config;
with AWS.Response;
with AWS.Status;
with AWS.MIME;
with AWS.Dispatchers.Callback;
with Handlers.Health;
with Handlers.Products;
package body API.Server is
WS : AWS.Server.HTTP;
function Dispatcher
(Request : AWS.Status.Data) return AWS.Response.Data
is
URI : constant String := AWS.Status.URI (Request);
begin
if URI = "/health" then
return Handlers.Health.Handle (Request);
elsif URI = "/products" or else URI'Length > 9
and then URI (URI'First .. URI'First + 8) = "/products"
then
return Handlers.Products.Handle (Request);
else
return AWS.Response.Build
(AWS.MIME.Application_JSON,
"{""error"":""not found""}",
Status_Code => AWS.Messages.S404);
end if;
end Dispatcher;
procedure Start (Port : Positive := 8080) is
Config : AWS.Config.Object := AWS.Config.Get_Current;
begin
AWS.Config.Set.Server_Port (Config, Port);
AWS.Config.Set.Max_Connection (Config, 64);
AWS.Server.Start
(WS, "Ada Web Service",
Callback => Dispatcher'Access,
Config => Config);
AWS.Server.Wait (AWS.Server.Forever);
end Start;
procedure Stop is
begin
AWS.Server.Shutdown (WS);
end Stop;
end API.Server;
Health Endpoint
-- src/handlers/health_handler.ads
with AWS.Response;
with AWS.Status;
package Handlers.Health is
function Handle
(Request : AWS.Status.Data) return AWS.Response.Data;
end Handlers.Health;
-- src/handlers/health_handler.adb
with AWS.Response;
with AWS.Status;
with AWS.MIME;
package body Handlers.Health is
function Handle
(Request : AWS.Status.Data) return AWS.Response.Data
is
pragma Unreferenced (Request);
begin
return AWS.Response.Build
(AWS.MIME.Application_JSON,
"{""status"":""ok"",""region"":""eu-central""}");
end Handle;
end Handlers.Health;
Products REST Handler with PostgreSQL
-- src/handlers/products_handler.adb
with AWS.Response;
with AWS.Status;
with AWS.MIME;
with AWS.Messages;
with GNATCOLL.SQL.Postgres;
with GNATCOLL.SQL.Exec;
with Ada.Environment_Variables;
package body Handlers.Products is
DB_Description : GNATCOLL.SQL.Exec.Database_Description;
DB : GNATCOLL.SQL.Exec.Database_Connection;
procedure Connect_DB is
DB_URL : constant String :=
Ada.Environment_Variables.Value ("DATABASE_URL");
begin
DB_Description :=
GNATCOLL.SQL.Postgres.Setup (Database => DB_URL);
DB := DB_Description.Build_Connection;
end Connect_DB;
function Handle
(Request : AWS.Status.Data) return AWS.Response.Data
is
Method : constant String :=
AWS.Status.Method (Request);
begin
if DB = null then
Connect_DB;
end if;
if Method = "GET" then
declare
Query : constant GNATCOLL.SQL.Exec.Prepared_Statement :=
GNATCOLL.SQL.Exec.Prepare
("SELECT id, name, price FROM products ORDER BY id",
On_Server => True);
Cursor : GNATCOLL.SQL.Exec.Forward_Cursor;
Result : GNATCOLL.Strings.XString;
begin
Cursor.Fetch (DB, Query);
Result.Append ("[");
while Cursor.Has_Row loop
if not Cursor.First then
Result.Append (",");
end if;
Result.Append
("{""id"":" & Cursor.Value (0)
& ",""name"":""" & Cursor.Value (1)
& """,""price"":" & Cursor.Value (2) & "}");
Cursor.Next;
end loop;
Result.Append ("]");
return AWS.Response.Build
(AWS.MIME.Application_JSON, Result.To_String);
end;
else
return AWS.Response.Build
(AWS.MIME.Application_JSON,
"{""error"":""method not allowed""}",
Status_Code => AWS.Messages.S405);
end if;
end Handle;
end Handlers.Products;
Main Entry Point
-- src/main.adb
with API.Server;
with Ada.Text_IO;
procedure Main is
begin
Ada.Text_IO.Put_Line ("Ada Web Service starting on port 8080");
Ada.Text_IO.Put_Line ("Region: EU-Central (sota.io)");
API.Server.Start (Port => 8080);
end Main;
Database Migration
Ada with GNATCOLL can run SQL migrations at startup:
-- src/migrations.adb
with GNATCOLL.SQL.Exec;
with Ada.Text_IO;
package body Migrations is
procedure Run (DB : GNATCOLL.SQL.Exec.Database_Connection) is
begin
DB.Execute
("CREATE TABLE IF NOT EXISTS products (" &
" id SERIAL PRIMARY KEY," &
" name VARCHAR(255) NOT NULL," &
" price NUMERIC(10,2) NOT NULL DEFAULT 0," &
" currency VARCHAR(3) NOT NULL DEFAULT 'EUR'," &
" created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()" &
")");
Ada.Text_IO.Put_Line ("Migrations complete");
end Run;
end Migrations;
Dockerfile for Production
Ada compiles to native binaries, which means the production Docker image can be extremely small — a statically linked Ada binary with no runtime dependencies:
# Stage 1 — Build
FROM ubuntu:24.04 AS builder
RUN apt-get update && apt-get install -y \
gnat \
gprbuild \
libaws-dev \
libgnatcoll-db2ada-dev \
libgnatcoll-sql-dev \
libssl-dev \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY . .
RUN gprbuild -P ada_web_service.gpr -j0
# Stage 2 — Minimal runtime
FROM ubuntu:24.04-minimal
RUN apt-get update && apt-get install -y \
libaws22 \
libgnatcoll-sql22 \
libpq5 \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
RUN useradd -r -u 1001 adauser
USER adauser
COPY --from=builder /app/bin/main .
EXPOSE 8080
ENTRYPOINT ["./main"]
The resulting container is dramatically smaller than a JVM service. An Ada binary serving a REST API with PostgreSQL connectivity typically produces an image under 80MB, with an idle RSS memory footprint under 20MB. For EU teams running many microservices, this density matters operationally.
Deploying to Europe with sota.io
Add a sota.yaml to your project root:
# sota.yaml
build:
dockerfile: Dockerfile
deploy:
port: 8080
region: eu-central
health_check: /health
env:
- DATABASE_URL
Deploy with:
sota deploy
sota.io builds the Ada binary in EU infrastructure, provisions a managed PostgreSQL instance in Frankfurt (same region as your service), and returns a live HTTPS URL — no Kubernetes, no VPCs, no load balancer configuration required.
Environment Variables
sota env set DATABASE_URL=postgresql://user:password@host:5432/dbname
Ada reads environment variables with the standard Ada.Environment_Variables package — no external dependency required.
SPARK: Formal Verification for the Most Critical EU Systems
Ada's most powerful feature for safety-critical EU deployments is SPARK — a formally verifiable subset of Ada maintained by AdaCore. SPARK allows developers to write mathematical proofs that a program cannot have buffer overflows, null pointer dereferences, race conditions, or arithmetic exceptions — at compile time, before the code runs.
This is why Ada (and SPARK) appears in:
- Airbus fly-by-wire — where a software bug could cause a crash
- SNCF ERTMS signalling — where a software bug could cause a collision
- Medical device firmware across the EU — where a software bug could kill a patient
- Ariane 6 guidance software — where a software bug means losing a €200M satellite
For EU teams building backends that interface with any of these systems, or that process data with safety implications, SPARK Ada is the language that EU regulators understand and accept. No other mainstream programming language provides the same formal verification toolchain with industrial certification (DO-178C, EN 50128, IEC 62443).
GDPR and EU Data Residency
Ada's typical deployment contexts in Europe — aerospace, defence, railways, nuclear — all have data sovereignty requirements that go beyond GDPR. Defence data must remain in EU member state infrastructure by law. Aviation safety data must remain accessible to EU regulators. Medical device data is subject to MDR and IVDR.
sota.io's EU-native infrastructure — physically located in Frankfurt, Germany — satisfies not just GDPR Article 5's data minimisation requirements, but the more stringent data localisation requirements of EU defence, aviation, and medical frameworks. All data stays in Germany. No US cloud provider data transfer agreements are involved.
Performance Profile
Ada produces native binaries with deterministic performance characteristics — a property that safety-critical systems require. Unlike JVM or interpreted languages, Ada's execution time is bounded and predictable:
| Metric | Ada (native) | Java Spring Boot | Node.js | Python FastAPI |
|---|---|---|---|---|
| Startup time | < 50ms | 4-8s | 300-800ms | 500ms-2s |
| RSS memory (idle) | 15-25MB | 280-350MB | 60-120MB | 80-150MB |
| First request latency | < 1ms | 200-800ms | 5-20ms | 10-50ms |
| Throughput (req/s) | 40,000-80,000 | 8,000-12,000 | 15,000-25,000 | 3,000-8,000 |
| Binary/image size | 20-80MB | 280MB (JRE) | 120MB | 200MB |
Ada's throughput numbers reflect the compiler's aggressive optimisation — GNAT generates code comparable to GCC C++ in performance, because it uses the same GCC backend. For EU services under latency or memory constraints, Ada's native compilation is a genuine advantage.
Deployment Comparison
| Feature | sota.io | Railway | Render | Fly.io |
|---|---|---|---|---|
| EU-native infrastructure | ✓ Frankfurt | ✗ US-default | ✓ Frankfurt | ✓ EU regions |
| GDPR Article 28 DPA | ✓ | ✗ | Partial | Partial |
| Managed PostgreSQL EU | ✓ same region | ✗ | ✓ | ✓ |
| Ada/GNAT auto-detect | ✓ via Dockerfile | ✓ via Dockerfile | ✓ | ✓ |
| SPARK-ready toolchain | ✓ (custom image) | ✓ | ✓ | ✓ |
| Data stays in EU | ✓ always | ✗ | Partial | Partial |
| Defence/medical compliance | ✓ | ✗ | ✗ | ✗ |
Ada was invented by a French engineer, maintained by a French company, and powers the safety-critical infrastructure of the European continent. The language was designed to run where failure is not acceptable — in aircraft, spacecraft, trains, and hospitals. Deploying an Ada service to European infrastructure is not a technical curiosity. It is a return to origin: a language built in Paris, running in Paris-connected data centres, serving the European systems it was created to protect.
See Also
- Deploy SPARK Ada to Europe — Ada's formally verifiable subset, maintained by AdaCore (Paris). SPARK proves the absence of buffer overflows, null pointer dereferences, and race conditions at compile time — the strongest EU safety certification path (DO-178C Level A, EN 50128, IEC 62443).
- Deploy Free Pascal to Europe — Free Pascal and Ada share the EU safety-critical/embedded market. Both are ISO-standardised, both target Airbus-adjacent systems, and Free Pascal's Object Pascal directly implements the Wirth tradition that influenced Ada's design principles.
- Deploy C++ to Europe — Bjarne Stroustrup 🇩🇰 (Aarhus University + Cambridge). Ada and C++ are the two main native-binary EU safety-critical languages — Ada under DO-178C and EN 50128, C++ under MISRA C++ and AUTOSAR. Both run in Airbus and Thales production systems.
- Deploy Simula to Europe — Ole-Johan Dahl 🇳🇴 + Kristen Nygaard 🇳🇴 (Oslo 1967). Simula's object model influenced Ada's package and type hierarchy. Both are European languages built for formal, structured programming — Norway 1967 to France 1983.