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

Deploy COBOL to Europe โ€” EU Banking Infrastructure & GDPR-Compliant Financial Workloads in 2026

There is no language more consequential to the European financial system than COBOL. The German Bundesbank processes hundreds of millions of settlement transactions daily through COBOL systems. Sociรฉtรฉ Gรฉnรฉrale's core banking platform โ€” one of the largest in France โ€” runs on COBOL. ING Bank's transaction processing infrastructure in the Netherlands is built on COBOL. The SWIFT interbank messaging network, which moves trillions of euros between European financial institutions every business day, interfaces with COBOL back-ends at nearly every major European bank. The EU financial system does not merely use COBOL โ€” it depends on it operationally in a way that has no equivalent in any other software domain.

COBOL was created in 1959 by a committee convened by the US Department of Defense, with Grace Hopper ๐Ÿ‡บ๐Ÿ‡ธ (Rear Admiral, US Navy) as the primary intellectual architect and Jean Sammet ๐Ÿ‡บ๐Ÿ‡ธ (IBM) as a key designer. The language was designed for business data processing โ€” reading and writing records, performing decimal arithmetic, producing reports โ€” with a deliberately readable English-like syntax intended to make programs comprehensible to business managers as well as programmers. That design philosophy turned out to be extraordinarily durable: COBOL programs written in the 1970s are still running in European banks today, largely unchanged, processing modern financial data.

The European COBOL ecosystem built its own institutional weight. MicroFocus, founded in 1976 in Berkhamsted, Hertfordshire, United Kingdom ๐Ÿ‡ฌ๐Ÿ‡ง, became the world's dominant provider of COBOL compilers and tooling for non-mainframe platforms. MicroFocus brought COBOL to PCs, Unix servers, and eventually cloud infrastructure โ€” making it possible for European banks to run COBOL workloads on commodity hardware rather than IBM mainframes. Today, MicroFocus (now part of OpenText, maintaining Cambridge UK as its COBOL centre) provides the toolchain that European financial institutions use to maintain, test, and modernise their COBOL estates. The Cambridge engineering team has been central to COBOL standardisation for decades.

GnuCOBOL, the open-source COBOL compiler maintained as a GNU project, makes COBOL accessible without commercial licensing. It compiles COBOL to C and then to native machine code via GCC, producing binaries that run on any Linux platform โ€” including Hetzner servers in Germany. GnuCOBOL supports COBOL-85, COBOL-2002, and COBOL-2014 dialects, covers MicroFocus extensions, and integrates with the PostgreSQL libpq library for direct database access. Modern COBOL on GnuCOBOL is a fully viable containerised service runtime.

The British Foundation: MicroFocus Cambridge

MicroFocus was founded in 1976 by Brian Reynolds and Phil Montague in Hertfordshire, UK, at a time when the COBOL market was exclusively IBM mainframe territory. The insight was that businesses running COBOL applications should be able to move those applications to less expensive hardware without rewriting them. MicroFocus built a COBOL runtime that ran on minicomputers and then PCs โ€” making COBOL portable across hardware generations.

The company's Cambridge, UK engineering centre became the global hub for COBOL compiler technology. Cambridge's mathematical traditions โ€” the university that produced Turing, Hardy, and Dirac โ€” shaped MicroFocus's approach to formal language semantics and compiler correctness. The Cambridge team contributed to ISO COBOL standardisation (ISO/IEC 1989:2014), worked on formal language specifications, and built the test infrastructure that validated COBOL compiler conformance across implementations.

MicroFocus's European customer base includes virtually every major European bank and insurance company. Deutsche Bundesbank, BNP Paribas ๐Ÿ‡ซ๐Ÿ‡ท, Commerzbank ๐Ÿ‡ฉ๐Ÿ‡ช, ABN AMRO ๐Ÿ‡ณ๐Ÿ‡ฑ, Nordea ๐Ÿ‡ธ๐Ÿ‡ช, UniCredit ๐Ÿ‡ฎ๐Ÿ‡น โ€” the European financial system's COBOL estate is maintained and extended using MicroFocus tooling from Cambridge. When GDPR came into force in 2018, it was MicroFocus Cambridge that provided the tooling allowing European banks to add GDPR compliance logic to their existing COBOL codebases without full rewrites.

The acquisition of MicroFocus by Hewlett Packard Enterprise in 2017, and then by OpenText in 2023, moved corporate ownership offshore. But the Cambridge engineering centre remains, and the European COBOL expertise accumulated there represents decades of institutional knowledge about how European financial systems actually process data.

Deploy COBOL on sota.io

sota.io runs on Hetzner infrastructure in Germany. Data stays in the EU by default. GDPR compliance is structural, not configurable. COBOL services deploy as Docker containers using GnuCOBOL on Debian.

Prerequisites

Step 1 โ€” Write a COBOL REST service

Modern COBOL can expose HTTP endpoints using GnuCOBOL's C interoperability and the libcurl or libmicrohttpd libraries. A common pattern for EU financial workloads is a transaction validation service that applies regulatory rules before committing to PostgreSQL.

COBOL transaction validator with PostgreSQL (via ESQL/C):

       IDENTIFICATION DIVISION.
       PROGRAM-ID. TRANSACTION-VALIDATOR.
       AUTHOR. sota.io-team.
      *> GDPR-compliant transaction validation service
      *> EU financial regulation: MiFID II + DORA compliance checks

       ENVIRONMENT DIVISION.
       CONFIGURATION SECTION.

       DATA DIVISION.
       WORKING-STORAGE SECTION.

       01 WS-TRANSACTION.
          05 WS-TX-ID          PIC X(36).
          05 WS-AMOUNT         PIC 9(13)V99 COMP-3.
          05 WS-CURRENCY       PIC X(3).
          05 WS-SENDER-IBAN    PIC X(34).
          05 WS-RECEIVER-IBAN  PIC X(34).
          05 WS-PURPOSE        PIC X(140).
          05 WS-TIMESTAMP      PIC X(26).

       01 WS-VALIDATION-RESULT.
          05 WS-VALID-FLAG     PIC X(1).
             88 TX-VALID       VALUE 'Y'.
             88 TX-INVALID     VALUE 'N'.
          05 WS-REJECT-CODE    PIC X(10).
          05 WS-REJECT-REASON  PIC X(200).

       01 WS-REGULATORY-LIMITS.
      *>   MiFID II Article 26: transaction reporting thresholds
          05 WS-MIFID-THRESHOLD   PIC 9(13)V99 VALUE 50000.00.
      *>   DORA: operational resilience monitoring flag
          05 WS-DORA-AUDIT-FLAG   PIC X(1) VALUE 'N'.

       01 WS-DB-STATUS          PIC 9(4).
       01 WS-RETURN-CODE        PIC 9(4).

      *> PostgreSQL connection (via ESQL-style call)
       01 WS-DB-URL             PIC X(500).
       01 WS-SQL-STMT           PIC X(2000).

       PROCEDURE DIVISION.

       MAIN-LOGIC.
           PERFORM INIT-ENVIRONMENT
           PERFORM VALIDATE-TRANSACTION
           PERFORM AUDIT-LOG-GDPR
           IF TX-VALID
               PERFORM PERSIST-TRANSACTION
           END-IF
           STOP RUN.

       INIT-ENVIRONMENT.
           MOVE FUNCTION STORED-CHAR-LENGTH(FUNCTION GETENV('DATABASE_URL'))
               TO WS-DB-STATUS
           IF WS-DB-STATUS = 0
               DISPLAY "ERROR: DATABASE_URL not set"
               MOVE 8 TO RETURN-CODE
               STOP RUN
           END-IF
           MOVE FUNCTION GETENV('DATABASE_URL') TO WS-DB-URL.

       VALIDATE-TRANSACTION.
           MOVE 'Y' TO WS-VALID-FLAG
      *>   Rule 1: Amount must be positive
           IF WS-AMOUNT <= 0
               MOVE 'N' TO WS-VALID-FLAG
               MOVE 'AMT-ZERO'   TO WS-REJECT-CODE
               MOVE 'Transaction amount must be positive per EU Payment Services Directive'
                   TO WS-REJECT-REASON
           END-IF
      *>   Rule 2: IBAN format validation (EU SEPA requirement)
           IF TX-VALID
               PERFORM VALIDATE-IBAN-FORMAT
           END-IF
      *>   Rule 3: MiFID II โ€” flag transactions above reporting threshold
           IF WS-AMOUNT >= WS-MIFID-THRESHOLD
               MOVE 'Y' TO WS-DORA-AUDIT-FLAG
               DISPLAY "MiFID II Article 26: transaction above reporting threshold โ€” flagged"
           END-IF.

       VALIDATE-IBAN-FORMAT.
      *>   SEPA IBAN: 2-letter country code + 2 check digits + up to 30 chars
      *>   EU member state country codes accepted
           IF WS-SENDER-IBAN(1:2) NOT = 'DE'
           AND WS-SENDER-IBAN(1:2) NOT = 'FR'
           AND WS-SENDER-IBAN(1:2) NOT = 'NL'
           AND WS-SENDER-IBAN(1:2) NOT = 'IT'
           AND WS-SENDER-IBAN(1:2) NOT = 'ES'
           AND WS-SENDER-IBAN(1:2) NOT = 'PL'
           AND WS-SENDER-IBAN(1:2) NOT = 'SE'
           AND WS-SENDER-IBAN(1:2) NOT = 'AT'
           AND WS-SENDER-IBAN(1:2) NOT = 'BE'
           AND WS-SENDER-IBAN(1:2) NOT = 'PT'
               MOVE 'N' TO WS-VALID-FLAG
               MOVE 'IBAN-CC'    TO WS-REJECT-CODE
               MOVE 'Sender IBAN country code not in SEPA zone'
                   TO WS-REJECT-REASON
           END-IF.

       AUDIT-LOG-GDPR.
      *>   GDPR Article 30: record of processing activities
      *>   DORA Article 10: ICT incident reporting log
           MOVE SPACES TO WS-SQL-STMT
           STRING
               "INSERT INTO gdpr_audit_log "
               "(tx_id, operation, legal_basis, timestamp, dora_flag) "
               "VALUES ('" DELIMITED SIZE
               WS-TX-ID DELIMITED SPACE
               "', 'VALIDATE', 'PSD2_ART73_FRAUD_PREVENTION', "
               "NOW(), '" DELIMITED SIZE
               WS-DORA-AUDIT-FLAG DELIMITED SIZE
               "')" DELIMITED SIZE
               INTO WS-SQL-STMT
           END-STRING
           CALL 'db-execute' USING WS-DB-URL WS-SQL-STMT WS-DB-STATUS.

       PERSIST-TRANSACTION.
           MOVE SPACES TO WS-SQL-STMT
           STRING
               "INSERT INTO transactions "
               "(id, amount, currency, sender_iban, receiver_iban, "
               "purpose, created_at, validated) "
               "VALUES ('" DELIMITED SIZE
               WS-TX-ID DELIMITED SPACE
               "', " DELIMITED SIZE
               WS-AMOUNT DELIMITED SIZE
               ", '" DELIMITED SIZE
               WS-CURRENCY DELIMITED SPACE
               "', '" DELIMITED SIZE
               WS-SENDER-IBAN DELIMITED SPACE
               "', '" DELIMITED SIZE
               WS-RECEIVER-IBAN DELIMITED SPACE
               "', '" DELIMITED SIZE
               WS-PURPOSE DELIMITED SPACE
               "', NOW(), TRUE)" DELIMITED SIZE
               INTO WS-SQL-STMT
           END-STRING
           CALL 'db-execute' USING WS-DB-URL WS-SQL-STMT WS-DB-STATUS.

HTTP wrapper (C shim for GnuCOBOL + libmicrohttpd):

/* server.c โ€” HTTP wrapper calling COBOL validation logic */
#include <microhttpd.h>
#include <libpq-fe.h>
#include <string.h>
#include <stdlib.h>

/* GnuCOBOL external declaration */
extern void transaction_validator(void);

static PGconn *db_connection = NULL;

/* db-execute called from COBOL via CALL 'db-execute' */
void db_execute(char *db_url, char *sql, int *status) {
    if (!db_connection || PQstatus(db_connection) != CONNECTION_OK) {
        db_connection = PQconnectdb(db_url);
    }
    PGresult *res = PQexec(db_connection, sql);
    *status = (PQresultStatus(res) == PGRES_COMMAND_OK) ? 0 : 1;
    PQclear(res);
}

static enum MHD_Result handle_request(
    void *cls, struct MHD_Connection *conn,
    const char *url, const char *method,
    const char *version, const char *upload_data,
    size_t *upload_data_size, void **ptr)
{
    if (strcmp(url, "/health") == 0) {
        const char *body = "{\"status\":\"ok\",\"region\":\"eu-central\","
                           "\"runtime\":\"GnuCOBOL\",\"server\":\"sota.io\"}";
        struct MHD_Response *resp = MHD_create_response_from_buffer(
            strlen(body), (void*)body, MHD_RESPMEM_PERSISTENT);
        MHD_add_response_header(resp, "Content-Type", "application/json");
        int ret = MHD_queue_response(conn, MHD_HTTP_OK, resp);
        MHD_destroy_response(resp);
        return ret;
    }
    /* Route /api/validate to COBOL program */
    if (strcmp(url, "/api/validate") == 0 && strcmp(method, "POST") == 0) {
        transaction_validator();  /* invoke COBOL validation logic */
        const char *body = "{\"validated\":true,\"jurisdiction\":\"EU\"}";
        struct MHD_Response *resp = MHD_create_response_from_buffer(
            strlen(body), (void*)body, MHD_RESPMEM_PERSISTENT);
        int ret = MHD_queue_response(conn, MHD_HTTP_OK, resp);
        MHD_destroy_response(resp);
        return ret;
    }
    return MHD_NO;
}

int main(void) {
    char *port_str = getenv("PORT");
    unsigned int port = port_str ? (unsigned int)atoi(port_str) : 8080;
    struct MHD_Daemon *daemon = MHD_start_daemon(
        MHD_USE_SELECT_INTERNALLY, port, NULL, NULL,
        &handle_request, NULL, MHD_OPTION_END);
    if (!daemon) return 1;
    printf("GnuCOBOL service on port %u (EU infrastructure โ€” sota.io)\n", port);
    pause();
    MHD_stop_daemon(daemon);
    return 0;
}

Makefile:

# Makefile โ€” GnuCOBOL + C hybrid build

CC = gcc
COBC = cobc

CFLAGS = -O2 $(shell pkg-config --cflags libmicrohttpd libpq)
LIBS   = $(shell pkg-config --libs libmicrohttpd libpq) -lcob

all: cobol-service

# Compile COBOL to object file (C intermediate)
transaction_validator.o: transaction_validator.cob
	$(COBC) -m -free transaction_validator.cob

# Link C wrapper + COBOL object
cobol-service: server.c transaction_validator.o
	$(CC) $(CFLAGS) -o cobol-service server.c transaction_validator.o $(LIBS)

clean:
	rm -f *.o cobol-service

Step 2 โ€” Containerise

FROM debian:bookworm-slim AS builder

RUN apt-get update && apt-get install -y \
    gnucobol \
    libmicrohttpd-dev \
    libpq-dev \
    gcc \
    make \
    pkg-config \
    && apt-get clean && rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY . .
RUN make

FROM debian:bookworm-slim

RUN apt-get update && apt-get install -y \
    libcob4 \
    libmicrohttpd12 \
    libpq5 \
    && apt-get clean && rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY --from=builder /app/cobol-service .

EXPOSE 8080
CMD ["./cobol-service"]

Step 3 โ€” Deploy to sota.io

# Install sota CLI
curl -sSL https://sota.io/install.sh | sh

# Initialise project
sota init

# Deploy โ€” builds Docker image, pushes to EU registry, starts service
sota deploy

# Check status
sota status

Your GnuCOBOL service is now running on Hetzner infrastructure in Germany. Traffic goes to your-project.sota.io over HTTPS automatically.

Step 4 โ€” Connect PostgreSQL

# Provision managed PostgreSQL
sota postgres create --name cobol-db

# Get connection string
sota postgres env cobol-db

In your COBOL program, DATABASE_URL is injected as an environment variable and accessed via FUNCTION GETENV('DATABASE_URL'). GnuCOBOL's C interoperability passes it directly to libpq's PQconnectdb() in the C shim.

       INIT-ENVIRONMENT.
           MOVE FUNCTION GETENV('DATABASE_URL') TO WS-DB-URL
           CALL 'db-connect' USING WS-DB-URL WS-DB-STATUS
           IF WS-DB-STATUS NOT = 0
               DISPLAY "Database connection failed"
               STOP RUN
           END-IF.

The managed PostgreSQL instance runs in the same Hetzner data centre as your COBOL service โ€” no cross-region data transfer, no US Cloud Act exposure for EU financial data.

COBOL and the EU Financial Regulatory Stack

European financial regulators have shaped COBOL's continuing evolution. The EU's financial regulatory framework โ€” PSD2, MiFID II, DORA, GDPR โ€” adds compliance obligations that COBOL-based systems must meet.

PSD2 (Payment Services Directive 2). PSD2 requires EU payment service providers to expose Open Banking APIs and implement Strong Customer Authentication. COBOL transaction processing cores at European banks expose PSD2-compliant REST APIs through middleware layers โ€” the COBOL handles the transactional integrity and the middleware handles API formatting. GnuCOBOL on sota.io can sit behind an API gateway, processing payment logic while the gateway handles OAuth and rate limiting.

MiFID II (Markets in Financial Instruments Directive 2). MiFID II Article 26 requires systematic internalisers and trading venues to report transactions above defined thresholds to national competent authorities (BaFin in Germany ๐Ÿ‡ฉ๐Ÿ‡ช, AMF in France ๐Ÿ‡ซ๐Ÿ‡ท, FCA in the UK ๐Ÿ‡ฌ๐Ÿ‡ง). COBOL systems at European investment banks handle this reporting logic โ€” checking thresholds, formatting reports, submitting to trade repositories. The transaction validator example above implements the MiFID II threshold check as a native COBOL rule.

DORA (Digital Operational Resilience Act). DORA, entering full application in January 2025, requires EU financial institutions to implement ICT risk management, incident reporting, and resilience testing. COBOL systems are explicitly in scope as critical ICT infrastructure. The WS-DORA-AUDIT-FLAG pattern in the example above is a direct implementation: every transaction that triggers DORA monitoring criteria (high value, unusual patterns) is flagged for the ICT incident reporting pipeline.

GDPR Article 9 financial data. Financial data โ€” account numbers, transaction histories, credit scores โ€” qualifies as sensitive personal data under GDPR where it reveals information about health (medical payments), religion (charitable donations), or political affiliation (party membership fees). COBOL's field-level data definitions map directly to GDPR data minimisation: working storage fields are explicitly scoped, named, and typed, making it straightforward to audit which fields contain personal data and implement field-level encryption or pseudonymisation.

GnuCOBOL and the Open-Source COBOL Revival

GnuCOBOL (formerly OpenCOBOL) is the GNU project's free, open-source COBOL compiler. It was initiated by Keisuke Nishida (Japan) and Roger While (Australia), and has been maintained since 2009 by Simon Sobisch ๐Ÿ‡ฉ๐Ÿ‡ช (Germany), who has been the primary maintainer and has driven GnuCOBOL's expansion to cover MicroFocus COBOL extensions, IBM COBOL dialect compatibility, and modern COBOL-2014 features.

Simon Sobisch's German maintainership is significant: GnuCOBOL's most intensive real-world testing happens against German banking workloads. The German financial sector's COBOL estate is one of the most demanding operational environments for COBOL correctness โ€” the Deutsche Bundesbank's settlement systems process transactions where a computation error means a regulatory breach. GnuCOBOL's focus on correct decimal arithmetic (using GMP for arbitrary-precision computation), correct PICTURE clause handling, and faithful implementation of COBOL's packed-decimal COMP-3 format reflects the demands of German financial workloads.

GnuCOBOL compiles to C and then to native code via GCC. A GnuCOBOL binary on an AMD EPYC server in Hetzner's Frankfurt data centre runs at native speed โ€” no interpreter, no JVM warm-up, no garbage collection pauses. For high-throughput transaction processing where latency consistency matters, native COBOL execution is a performance advantage.

COBOL vs Modern Backend Languages for EU Financial Workloads

FeatureGnuCOBOL on sota.ioJava/Spring on sota.ioPython on sota.io
Decimal arithmeticNative COMP-3 packed decimalBigDecimal (JDK)decimal module
EU regulatory historyDecades of BaFin/MiFID integrationStrong enterprise adoptionGrowing fintech presence
Execution modelNative binary (via GCC)JVM (JIT, warm-up)Interpreted / CPython
GDPR field-level auditWorking storage explicit fieldsAnnotation-based frameworksDecorator-based frameworks
MicroFocus compatibilityGnuCOBOL dialect extensionsN/AN/A
EU originMicroFocus Cambridge ๐Ÿ‡ฌ๐Ÿ‡ง toolchainOracle ๐Ÿ‡บ๐Ÿ‡ธ JDKPSF ๐Ÿ‡บ๐Ÿ‡ธ
Legacy integrationNative (.cob existing files run unchanged)JNI/COBOL bridgesctypes/CFFI bridges
GDPR jurisdictionEU (Hetzner, Germany)EU (Hetzner, Germany)EU (Hetzner, Germany)

GDPR and COBOL on sota.io

GDPR compliance for COBOL services on sota.io:

Data residency. All data processed by your COBOL service stays in Hetzner's German data centres. The Deutsche Bundesbank uses Frankfurt-based infrastructure โ€” your GnuCOBOL service on Hetzner Frankfurt operates in the same regulatory geography as Germany's central bank. No US Cloud Act exposure for EU financial data.

Field-level personal data control. COBOL's DATA DIVISION is a precise map of every data field the program uses. GDPR's data minimisation principle (Article 5(1)(c)) is naturally enforced: only fields that exist in WORKING-STORAGE or FILE SECTION can be processed. Auditing personal data fields means reading the DATA DIVISION.

COMP-3 and encryption. Packed-decimal COMP-3 fields storing financial amounts can be encrypted at rest using PostgreSQL's pgcrypto extension, with decryption keys managed via sota.io's environment variable injection. This satisfies GDPR Article 32's technical security measures for financial personal data.

Audit trail. The AUDIT-LOG-GDPR paragraph pattern shown above โ€” writing to an append-only gdpr_audit_log table for every processing operation โ€” implements GDPR Article 30's record of processing activities for financial transaction data, with PSD2 legal basis and DORA ICT event flags.

Minimal dependency surface. A GnuCOBOL binary compiled from a .cob source file has a deterministic, auditable dependency graph: GnuCOBOL runtime (libcob), libpq for PostgreSQL, and any explicitly linked C libraries. For the EU Cyber Resilience Act's SBOM requirements, this small dependency surface minimises compliance burden.

Why sota.io for COBOL

EU infrastructure by default. Hetzner Germany. No US region fallback. GDPR data residency without configuration.

Managed PostgreSQL. Provisioned in the same data centre as your COBOL service. Connection strings injected as environment variables. DATABASE_URL accessible directly from COBOL via FUNCTION GETENV. Backups, failover, and version upgrades managed.

Zero DevOps. Push code, sota deploy, done. No Kubernetes clusters to manage, no ingress controllers, no TLS certificate renewal scripts.

Docker-based deployment. GnuCOBOL services deploy as Docker containers. gnucobol is packaged in Debian's standard repositories. The multi-stage Dockerfile pattern produces minimal runtime images.

German company. No US legal jurisdiction. No Cloud Act exposure. Data processing agreements under GDPR Article 28 with a German data processor.


COBOL is the language of European finance. MicroFocus (Cambridge ๐Ÿ‡ฌ๐Ÿ‡ง) built the toolchain that brought COBOL to every platform; Simon Sobisch ๐Ÿ‡ฉ๐Ÿ‡ช maintains GnuCOBOL to the correctness standards that German banking demands; Deutsche Bundesbank, Sociรฉtรฉ Gรฉnรฉrale, and ING trust COBOL with trillions of euros of daily settlement. Modern GnuCOBOL containerises and deploys to cloud infrastructure with full GDPR compliance โ€” the transactional correctness and decimal arithmetic precision that EU financial regulation demands, running on EU infrastructure with no US jurisdiction exposure. sota.io provides the Hetzner-backed, German-operated platform that EU financial workloads deserve.

Deploy your first COBOL service to EU infrastructure โ†’

See also: Deploy ABAP to Europe โ†’, Deploy REXX/NetRexx to Europe โ†’, Deploy Fortran to Europe โ†’