2026-04-01ยท9 min readยทsota.io team

Deploy Ballerina to Europe โ€” Network-Native Cloud Language on EU Infrastructure in 2026

The most common source of GDPR data incidents is not a rogue process or a stolen credential โ€” it is unvalidated data flowing between services with no type system watching the boundary. HTTP calls return any. JSON payloads get cast with runtime checks nobody maintains. One field renamed in one service breaks twelve others at 2 AM. Ballerina solves this at the language level: network interactions are first-class typed constructs, not library calls. REST endpoints, GraphQL schemas, and gRPC services are part of the language grammar, checked at compile time, generating sequence diagrams automatically for audit trails.

Ballerina was designed at WSO2 and its principal language architect is James Clark ๐Ÿ‡ฌ๐Ÿ‡ง โ€” a British computer scientist who shaped the modern web's foundational standards. Clark wrote the Expat XML parser (embedded in Python, PHP, Perl, and countless EU government systems). He designed XSLT, XPath, XPointer, and RelaxNG at the W3C. He is the author of IETF RFC 2396 bis and co-edited the XML Namespaces specification. The W3C's XML infrastructure โ€” the data exchange layer for European e-government, EU VAT systems, and cross-border regulatory reporting โ€” was substantially built by James Clark. Ballerina is his vision for what a language looks like when network types are as native as integers.

Ballerina is Apache 2.0 licensed, runs on GraalVM (native binary) or JVM, and deploys to any EU Linux server. sota.io runs Ballerina on Hetzner infrastructure in Germany โ€” EU-sovereign, GDPR-compliant by default.

James Clark โ€” British Engineer Who Standardised the Web's Data Layer

James Clark ๐Ÿ‡ฌ๐Ÿ‡ง is one of the most quietly influential figures in computing. His work is invisible precisely because it became universal: every browser parses XML via specifications he wrote; every XSLT transformation runs on algorithms he designed; every European government portal exchanging structured data does so over formats Clark standardised at the W3C in the 1990s and 2000s.

Clark's contributions to open standards include:

Clark joined WSO2 as a principal engineer, where he brought the same rigour to network API design that he had applied to XML standards. The result was Ballerina: a language where HTTP services, JSON transformations, and database interactions are first-class citizens of the type system โ€” not afterthoughts delegated to frameworks.

WSO2 maintains offices in the United Kingdom and across Europe. Ballerina's toolchain is Apache 2.0 licensed, which means EU organisations can deploy, audit, and modify it without vendor lock-in. The European Central Bank, European Commission, and multiple EU member-state governments use WSO2 middleware built on the same technical foundation as Ballerina.

What Makes Ballerina Distinctive

Network Types Are First-Class

In Ballerina, a REST service is not a class annotated with @RestController. It is a service object with resource function methods typed by HTTP method and path. The compiler checks the types. The toolchain generates sequence diagrams from the source code.

import ballerina/http;
import ballerina/log;

// EU GDPR-compliant data subject service
// Network types checked at compile time โ€” no runtime cast surprises

type DataSubject record {|
    string subjectId;        // pseudonymised โ€” no plain PII
    string dataResidency;    // always "EU-DE" on sota.io
    string legalBasis;       // Art. 6 GDPR
    int retentionDays;       // HGB ยง257: max 2556 days
    boolean consentGiven;
|};

type ConsentRequest record {|
    string subjectId;
    string purpose;          // Art. 5(1)(b) GDPR: purpose limitation
    string legalBasis;
|};

service /gdpr on new http:Listener(8080) {

    // GET /gdpr/subject/{id} โ€” retrieve data subject record
    resource function get subject/[string subjectId]() 
        returns DataSubject|http:NotFound {
        
        // In production: query sota.io managed PostgreSQL
        DataSubject subject = {
            subjectId: subjectId,
            dataResidency: "EU-DE",          // Hetzner Germany
            legalBasis: "Art. 6(1)(b) GDPR",
            retentionDays: 730,
            consentGiven: true
        };
        return subject;
    }

    // POST /gdpr/consent โ€” record consent
    resource function post consent(@http:Payload ConsentRequest req) 
        returns http:Accepted|http:BadRequest {
        
        log:printInfo("Consent recorded", subjectId = req.subjectId,
                      purpose = req.purpose, legalBasis = req.legalBasis);
        return http:ACCEPTED;
    }
}

The DataSubject record type guarantees that every response carries dataResidency and legalBasis fields โ€” checked at compile time. No GDPR field can be accidentally omitted. No runtime NullPointerException on a consent endpoint.

JSON and XML Are Native Types

Ballerina treats JSON and XML not as string serialisation formats but as native data types with their own syntax. This eliminates the most common source of GDPR data leakage: uncontrolled JSON transformation where extra fields pass through unchecked.

import ballerina/http;

// XML is a native Ballerina type โ€” no import, no library
// EU SEPA payment XML (ISO 20022 format) handled natively

type SepaPayment record {|
    string messageId;
    string creationDateTime;
    decimal amount;
    string currency;        // must be "EUR" for SEPA
    string debtorIban;
    string creditorIban;
|};

service /payments on new http:Listener(8080) {

    resource function post sepa(@http:Payload SepaPayment payment) 
        returns xml|http:BadRequest {

        if payment.currency != "EUR" {
            return http:BAD_REQUEST;
        }

        // Generate ISO 20022 XML natively โ€” no string concatenation, no injection risk
        xml sepaXml = xml `<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.11">
            <CstmrCdtTrfInitn>
                <GrpHdr>
                    <MsgId>${payment.messageId}</MsgId>
                    <CreDtTm>${payment.creationDateTime}</CreDtTm>
                </GrpHdr>
                <PmtInf>
                    <Amt><InstdAmt Ccy="${payment.currency}">${payment.amount}</InstdAmt></Amt>
                </PmtInf>
            </CstmrCdtTrfInitn>
        </Document>`;

        return sepaXml;
    }
}

James Clark's XML expertise is visible here: Ballerina's XML literal syntax prevents injection at the type level. A string cannot be interpolated into an XML position that expects an element name. XSS via XML construction is a compile error.

Sequence Diagrams Generated Automatically

Ballerina's toolchain generates sequence diagrams from service source code automatically. In a regulated EU sector โ€” financial services under MiFID II, healthcare under MDR, public procurement under DORA โ€” this means the interaction diagram required for audit documentation is always current and always matches the deployed code.

import ballerina/http;
import ballerinax/postgresql;
import ballerinax/postgresql.driver as _;

// This service's interaction diagram is generated by:
// bal doc --output ./diagrams
// The diagram shows:
//   Client โ†’ /api/data โ†’ PostgreSQL (EU-DE) โ†’ Client
// Automatically. No Confluence page to maintain.

configurable string host = ?;
configurable int port = 5432;
configurable string database = ?;
configurable string username = ?;
configurable string password = ?;

final postgresql:Client dbClient = check new (host, username, password, database, port);

type AuditRecord record {|
    int id;
    string action;
    string dataResidency;
    string timestamp;
|};

service /api on new http:Listener(8080) {

    resource function get data() returns AuditRecord[]|error {
        // Query returns typed records โ€” no untyped ResultSet iteration
        stream<AuditRecord, error?> result = 
            dbClient->query(`SELECT id, action, data_residency, timestamp 
                             FROM audit_log 
                             WHERE data_residency = 'EU-DE'
                             ORDER BY timestamp DESC 
                             LIMIT 100`);
        return from AuditRecord rec in result select rec;
    }
}

The auto-generated sequence diagram documents exactly which services talk to which databases, in which order, with which data types. Under the EU AI Act (Article 13 transparency) and DORA (digital operational resilience), this documentation is mandatory โ€” Ballerina generates it for free.

Deploy Ballerina on sota.io

Prerequisites

Step 1 โ€” Install Ballerina

# Download from ballerina.io (Apache 2.0 licensed)
# Linux x64 โ€” runs on EU servers natively
curl -sL https://dist.ballerina.io/downloads/2201.10.0/ballerina-2201.10.0-linux-x64.deb -o ballerina.deb
sudo dpkg -i ballerina.deb

# Create new Ballerina project
bal new eu-service
cd eu-service

Step 2 โ€” Dockerfile (JVM or GraalVM native)

# Stage 1: Build Ballerina fat JAR
FROM ballerina/ballerina:2201.10.0 AS build

WORKDIR /app
COPY . .

# Build self-contained JAR โ€” includes all dependencies
RUN bal build

# Stage 2: Minimal JRE runtime
FROM eclipse-temurin:21-jre-alpine

RUN addgroup -S ballerina && adduser -S ballerina -G ballerina

WORKDIR /app
COPY --from=build /app/target/bin/eu_service.jar .

USER ballerina
EXPOSE 8080

CMD ["java", "-jar", "eu_service.jar"]

For GraalVM native compilation (faster startup, lower memory โ€” ideal for sota.io's flat-rate pricing):

# GraalVM native image โ€” cold start under 50ms
FROM ghcr.io/graalvm/native-image:21 AS build

WORKDIR /app
COPY . .

# Ballerina GraalVM native build
RUN bal build --graalvm

FROM debian:bookworm-slim

WORKDIR /app
COPY --from=build /app/target/bin/eu_service .

EXPOSE 8080
CMD ["./eu_service"]

Step 3 โ€” GDPR Configuration in Ballerina

Ballerina's Config.toml pattern keeps GDPR-sensitive configuration out of source code:

# Config.toml โ€” populated from sota.io environment variables
# Never committed to git

host = ""           # injected by sota.io at runtime
port = 5432
database = ""       # sota.io managed PostgreSQL (EU-DE)
username = ""
password = ""       # sota.io secret management

[gdpr]
dataResidency = "EU-DE"
retentionDays = 730          # 2 years: standard B2B retention
legalBasis = "Art. 6(1)(b) GDPR"
processorName = "sota.io"
processorCountry = "DE"

Step 4 โ€” sota.io Deployment

# Deploy Ballerina service to EU infrastructure
sota deploy

# Output:
# Building Docker image...
# Deploying to Hetzner Germany (eu-central)...
# TLS certificate provisioned
# Service running at https://your-ballerina-app.sota.io
# Region: EU (Germany) โ€” GDPR-compliant by default

Ballerina and the EU AI Act

The EU AI Act (Regulation 2024/1689), fully applicable from August 2026, requires high-risk AI systems to provide machine-readable technical documentation of their data flows, API contracts, and audit trails. Ballerina's auto-generated sequence diagrams and typed API contracts are exactly what Article 13 transparency requirements demand.

A Ballerina service that feeds data to a high-risk AI system produces, from source code alone:

Under DORA (Digital Operational Resilience Act), EU financial institutions must document their ICT dependencies. A Ballerina microservice architecture generates this documentation automatically from code. Compliance is a build artifact, not a separate deliverable.

European Legacy: XML Standards to Cloud-Native Architecture

James Clark's trajectory from XML standards to Ballerina reflects European technical culture: rigour first, pragmatism second. The W3C XML working groups โ€” where Clark co-authored XSLT, XPath, and XML Namespaces โ€” were substantially European institutions in their early years. Tim Berners-Lee ๐Ÿ‡ฌ๐Ÿ‡ง, Clark ๐Ÿ‡ฌ๐Ÿ‡ง, and the majority of the XML core committee worked from European research contexts.

The lineage of EU digital infrastructure standards runs through Clark's work:

Ballerina brings Clark's XML-era insight to the microservices era: the data format and transport protocol should be typed and safe at the language level, not validated only at runtime. On sota.io's EU infrastructure, Ballerina backends run where their regulatory requirements apply โ€” in Germany, on GDPR-compliant servers, with data that never crosses to non-EU jurisdictions.

Why sota.io for Ballerina

EU-native infrastructure: Hetzner Germany. Data never leaves the EU. GDPR compliance is structural, not configured.

Simple deployment: sota deploy from your project directory. No Kubernetes. No cloud console. No IAM policies.

Flat-rate pricing: โ‚ฌ9/month for 2 GB RAM, 2 vCPU, managed PostgreSQL. GraalVM native images start in under 50ms and fit comfortably in 256 MB โ€” efficient use of sota.io's flat-rate allocation.

Automatic TLS: HTTPS certificate provisioned within seconds of deployment.

Regulatory documentation for free: Ballerina generates OpenAPI specs and sequence diagrams from source code. On sota.io, these become part of your GDPR Art. 30 processing record and EU AI Act technical documentation โ€” automatically.


Sign up for sota.io โ†’ โ€” Deploy Ballerina and 68 other languages on EU infrastructure in minutes. (69 total)