2026-04-01Β·9 min readΒ·sota.io team

Deploy Logtalk to Europe β€” Object-Oriented Logic Programming on EU Infrastructure in 2026

Logic programming has a long history in European computer science. Prolog was invented in Marseille by Alain Colmerauer πŸ‡«πŸ‡· in 1972. It became the foundation for expert systems, natural language processing, constraint solving, and AI reasoning systems that shaped European research institutions from the 1970s through today. But Prolog, for all its power, lacks the structural organisation mechanisms that modern software engineering requires. There are no interfaces. No formal module composition. No separation between specification and implementation.

Logtalk fills exactly that gap. Created in 1998 by Paulo Moura πŸ‡΅πŸ‡Ή at the University of Beira Interior in CovilhΓ£, Portugal, Logtalk is an object-oriented logic programming language that compiles to ISO Prolog. It brings objects, protocols (interfaces), and categories (mixins) to logic programming β€” making it possible to build large, maintainable knowledge systems with the same structural discipline that Java or OCaml enforce for object-oriented and functional code. Logtalk runs on top of virtually any ISO-compliant Prolog system: SWI-Prolog, ECLiPSe, SICStus, GNU Prolog, LVM, Tau Prolog, and more.

Logtalk is an EU-origin language, built and maintained by a Portuguese researcher with Portuguese public research funding, designed for the kind of structured knowledge engineering that EU regulated sectors β€” healthcare, finance, legal, public administration β€” increasingly need. It deploys on sota.io.

The Portuguese Origin: University of Beira Interior

Paulo Moura πŸ‡΅πŸ‡Ή is a Portuguese software engineer and researcher at the University of Beira Interior (Universidade da Beira Interior, UBI) in CovilhΓ£, Portugal β€” a city in the Serra da Estrela region, home to one of Portugal's oldest universities. UBI has strong traditions in computer science, engineering, and formal methods, situated in a region historically known for precision manufacturing and now increasingly for technology research.

Moura began developing Logtalk in 1998 while working on the problem of how to structure large Prolog programs. At the time, Prolog's module system β€” where one existed β€” varied substantially between implementations, was not part of the ISO standard, and provided only namespace separation rather than true object-oriented encapsulation or protocol-based polymorphism. Logtalk was designed to solve this: a meta-language that compiles to standard Prolog, adding objects, protocols, and categories while remaining fully compatible with the underlying Prolog system's built-in predicates, libraries, and development tools.

The key insight was portability. Rather than implementing a new Prolog runtime, Logtalk generates standard Prolog code that any ISO-compliant Prolog system can run. This means Logtalk applications can run on SWI-Prolog's mature library ecosystem, on ECLiPSe's constraint solving infrastructure, on SICStus Prolog's commercial runtime with its real-time guarantees, or on GNU Prolog compiled to native code. The choice of Prolog backend becomes a deployment decision, not a language commitment.

Logtalk's development has been supported by FCT β€” the FundaΓ§Γ£o para a CiΓͺncia e a Tecnologia, Portugal's national research funding agency, which operates under the Portuguese Ministry of Science and Technology and funds fundamental and applied research across Portuguese universities. FCT funding represents EU research investment channelled through Portugal's scientific infrastructure: Horizon Europe partnerships, Marie Curie fellowships, and EU structural funds flow through FCT to Portuguese researchers including the Logtalk project.

Logtalk's Object Model

Logtalk's contribution is not syntax sugar. It is a principled object model for logic programming with a clear formal semantics.

Objects. A Logtalk object is a self-contained unit of code and data: it encapsulates predicates (logic programming's equivalent of methods and data access functions) and controls which predicates are public, protected, or private. Objects in Logtalk can be static (defined at compile time) or dynamic (created at runtime). Unlike Prolog's assert/retract model for dynamic code, Logtalk objects provide controlled mutation with explicit boundaries.

Protocols. Logtalk protocols are interfaces: they declare a set of predicates that objects implementing the protocol must define. This is the logic programming equivalent of Java interfaces, OCaml module signatures, or Go interfaces. Protocol-based polymorphism means that a predicate expecting a data_source protocol can work with any object that implements that protocol β€” a database connector, a CSV reader, a REST API client β€” without knowing the implementation details.

Categories. Logtalk categories are reusable predicate collections β€” mixins in the object-oriented sense. A category can be imported by any object that needs its predicates. Categories allow code reuse without inheritance: a gdpr_audit_logging category can be imported by any object handling personal data, adding GDPR Article 30 record-keeping predicates without requiring a common ancestor class.

Message sending. Logtalk uses a message-passing model that maps naturally to the declarative style of logic programming. Sending message find_users(Role, Users) to the user_registry object produces a binding for Users through the object's logic clauses β€” the same way a Prolog goal produces bindings through clause resolution, but scoped to the object.

Meta-predicates and lambda expressions. Logtalk extends Prolog's meta-predicate model with typed meta-predicates and lambda expressions for higher-order programming. This makes it straightforward to implement functional-style transformations over knowledge structures β€” mapping, filtering, folding β€” with the same declarative clarity as standard Prolog.

Deploy Logtalk on sota.io

sota.io runs on Hetzner infrastructure in Germany. Data stays in the EU by default. GDPR compliance is structural, not configurable. Logtalk services deploy as Docker containers with any supported Prolog backend.

Prerequisites

Step 1 β€” Write a Logtalk knowledge service

Define a protocol and implementing object:

% gdpr_store.lgt β€” GDPR-compliant data store protocol + implementation

:- protocol(data_store_protocol).

  :- info([
    version is 1:0:0,
    author is 'Paulo Moura',  % Following Logtalk documentation conventions
    comment is 'Protocol for GDPR-compliant data stores.'
  ]).

  :- public(find_user/2).
  :- mode(find_user(+atom, -compound), zero_or_one).
  :- info(find_user/2, [
    comment is 'Finds a user by ID. Fails if not found.',
    argnames is ['UserID', 'User']
  ]).

  :- public(store_user/1).
  :- mode(store_user(+compound), one).

  :- public(erase_user/1).
  :- mode(erase_user(+atom), one).
  :- info(erase_user/1, [
    comment is 'GDPR Article 17: erases all personal data for UserID.'
  ]).

:- end_protocol.


% PostgreSQL-backed implementation
:- object(postgres_user_store,
  implements(data_store_protocol)).

  :- use_module(library(odbc)).  % SWI-Prolog ODBC/JDBC bindings

  find_user(UserID, user(UserID, Name, Email, CreatedAt)) :-
    getenv('DATABASE_URL', DSN),
    odbc_connect(DSN, Connection, []),
    odbc_query(Connection,
      'SELECT name, email, created_at FROM users WHERE id = ?',
      [UserID],
      row(Name, Email, CreatedAt)),
    odbc_disconnect(Connection).

  store_user(user(UserID, Name, Email, _CreatedAt)) :-
    getenv('DATABASE_URL', DSN),
    odbc_connect(DSN, Connection, []),
    odbc_query(Connection,
      'INSERT INTO users (id, name, email, created_at) VALUES (?, ?, ?, NOW())',
      [UserID, Name, Email], _),
    odbc_disconnect(Connection).

  erase_user(UserID) :-
    getenv('DATABASE_URL', DSN),
    odbc_connect(DSN, Connection, []),
    % GDPR Article 17: anonymise rather than hard-delete for audit trail
    odbc_query(Connection,
      'UPDATE users SET name = ?, email = ?, erased_at = NOW() WHERE id = ?',
      ['[Erased]', atom_concat('erased+', UserID, AnonEmail), AnonEmail, UserID], _),
    odbc_disconnect(Connection).

:- end_object.

GDPR audit logging category (reusable mixin):

% gdpr_audit.lgt β€” GDPR Article 30 record-keeping as a reusable category

:- category(gdpr_audit_category).

  :- info([
    comment is 'Reusable GDPR Article 30 audit logging. Import into any object handling personal data.'
  ]).

  :- public(log_data_access/3).
  :- mode(log_data_access(+atom, +atom, +atom), one).

  log_data_access(UserID, Operation, LegalBasis) :-
    get_time(Timestamp),
    format(atom(Entry),
      'GDPR-LOG: operation=~w user=~w basis=~w timestamp=~w',
      [Operation, UserID, LegalBasis, Timestamp]),
    % In production: write to append-only audit log table
    writeln(Entry).

:- end_category.


% Object that imports the audit category
:- object(audited_user_service,
  imports(gdpr_audit_category),
  implements(data_store_protocol),
  extends(postgres_user_store)).

  find_user(UserID, User) :-
    ^^find_user(UserID, User),  % Delegation to parent (postgres_user_store)
    ::log_data_access(UserID, read, 'legitimate_interest').

  erase_user(UserID) :-
    ::log_data_access(UserID, erasure, 'gdpr_art17_right_to_erasure'),
    ^^erase_user(UserID).

:- end_object.

HTTP REST service using SWI-Prolog HTTP libraries:

% server.lgt β€” HTTP server wrapping Logtalk knowledge objects

:- object(user_api_server).

  :- use_module(library(http/thread_httpd)).
  :- use_module(library(http/http_dispatch)).
  :- use_module(library(http/http_json)).

  :- http_handler('/api/users', ::handle_users, []).
  :- http_handler('/api/users/erase', ::handle_erasure, [method(post)]).
  :- http_handler('/health', ::handle_health, []).

  start(Port) :-
    http_server(http_dispatch, [port(Port)]),
    format("Logtalk API server running on port ~w (EU infrastructure)~n", [Port]).

  handle_health(_Request) :-
    reply_json(json([status=ok, region='eu-central', server='sota.io'])).

  handle_users(Request) :-
    http_parameters(Request, [id(UserID, [atom])]),
    (   audited_user_service::find_user(UserID, User)
    ->  User = user(ID, Name, Email, Created),
        reply_json(json([id=ID, name=Name, email=Email, created_at=Created]))
    ;   reply_json(json([error='user not found']), [status(404)])
    ).

  handle_erasure(Request) :-
    http_read_json_dict(Request, Data),
    UserID = Data.user_id,
    audited_user_service::erase_user(UserID),
    reply_json(json([status=erased, user_id=UserID])).

:- end_object.

Entry point (main.pl β€” standard Prolog loader):

% main.pl β€” loads Logtalk + application objects, starts server

:- use_module(library(logtalk)).

:- logtalk_load([
  gdpr_audit,          % category: audit logging mixin
  gdpr_store,          % protocol + postgres_user_store object
  audited_user_service, % extends postgres_user_store + imports gdpr_audit_category
  server               % HTTP API server object
]).

:- initialization(
  (   getenv('PORT', PortAtom)
  ->  atom_number(PortAtom, Port)
  ;   Port = 8080
  ),
  user_api_server::start(Port)
).

Step 2 β€” Containerise

FROM debian:bookworm-slim

RUN apt-get update && apt-get install -y \
    swi-prolog \
    logtalk \
    && apt-get clean && rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY *.lgt *.pl ./

# Verify Logtalk loads correctly
RUN swipl -g "use_module(library(logtalk)), halt" -t halt

EXPOSE 8080
CMD ["swipl", "-f", "main.pl"]

For multi-stage builds with SICStus Prolog (commercial, real-time guarantees):

FROM debian:bookworm-slim AS builder

RUN apt-get update && apt-get install -y logtalk
# SICStus installation assumed at /opt/sicstus
COPY --from=sicstus-base /opt/sicstus /opt/sicstus
ENV PATH="/opt/sicstus/bin:$PATH"

WORKDIR /app
COPY *.lgt *.pl ./

# Compile to SICStus saved state for fast startup
RUN sicstus -f main.pl --goal "save_program('app.sav'), halt"

FROM debian:bookworm-slim
COPY --from=builder /opt/sicstus /opt/sicstus
COPY --from=builder /app/app.sav /app/app.sav
ENV PATH="/opt/sicstus/bin:$PATH"
EXPOSE 8080
CMD ["sicstus", "--restore", "/app/app.sav"]

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 Logtalk 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 logtalk-db

# Get connection string
sota postgres env logtalk-db

In your Logtalk objects, the DATABASE_URL environment variable is injected automatically. SWI-Prolog's ODBC or library(pgsql) connects directly, and the connection string is accessible via getenv('DATABASE_URL', DSN).

% Pattern: connection helper category
:- category(postgres_connector).

  db_connect(Connection) :-
    getenv('DATABASE_URL', DSN),
    odbc_connect(DSN, Connection, [
      open(once),
      auto_close(true)
    ]).

  db_query(Connection, SQL, Params, Rows) :-
    odbc_query(Connection, SQL, Params, Rows).

:- end_category.

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

Logtalk and the EU AI Act

The EU AI Act, which entered into force in August 2024 and is being phased in through 2026, imposes explainability requirements on high-risk AI systems deployed in the EU. Systems making decisions about employment, credit, healthcare, and public administration must be able to explain their decisions to affected persons and to competent authorities.

Logtalk is uniquely positioned for EU AI Act compliance because logic programming systems are inherently explainable. A Logtalk-based rule engine produces decisions through explicit logical inference β€” each decision is derivable from a traceable chain of rules and facts. There is no black-box statistical model. There is no neural network whose activations cannot be inspected.

Proof trees as explanations. When a Prolog goal succeeds, the resolution trace records exactly which clauses were used, in what order, with what variable bindings. Logtalk can expose this trace as an explanation: "This credit application was rejected because: income_insufficient(applicant_a) was derived from monthly_income(applicant_a, 1800) and minimum_income_threshold(2000) under regulation EU_CRD_IV_article_73." This is a legally usable explanation for EU AI Act Article 13 transparency requirements.

Rule formalisation as audit artifacts. Logtalk objects encode decision rules as formal logic β€” risk_category(applicant, high) :- outstanding_debt(applicant, D), D > 50000. These rules are auditable by regulators, version-controlled in git, and can be compared across time to demonstrate that the AI system has not silently changed its decision logic.

Protocol-based compliance layers. A Logtalk protocol eu_ai_act_compliant can declare the predicates that any high-risk AI system component must implement: explain_decision/2, log_decision/3, provide_appeal_mechanism/1. Objects implementing the protocol are statically verified by the Logtalk compiler to provide all required predicates.

EU institutions and Prolog heritage. The EU has a long institutional history with logic programming. The European Computer Research Centre (ECRC) in Munich developed ECLiPSe Prolog, now maintained as open-source. INRIA in France has been central to Prolog research since Colmerauer's original work. The Austrian Institute of Technology uses logic programming for formal verification. These institutional roots mean that EU technical regulators understand logic programming in a way that makes Logtalk-based compliance documentation legible.

Logtalk's Prolog Backend Portability

One of Logtalk's most valuable engineering properties is its backend portability. The same Logtalk source files compile and run correctly on:

This portability means that choosing Logtalk is not a commitment to a specific vendor or runtime. EU organisations can start with SWI-Prolog (open-source, permissive licence), move to SICStus Prolog for production performance, and compile to GNU Prolog for embedded deployments β€” all using the same Logtalk source code.

Comparison: Logtalk vs Conventional Backend Approaches

FeatureLogtalk on sota.ioPython/FastAPI on sota.ioNode.js on sota.io
Reasoning modelDeclarative logic + OOPImperative + OOPImperative + async
EU AI Act explainabilityInherent (proof traces)Requires external XAI toolingRequires external XAI tooling
Rule encodingFirst-class (Prolog clauses)Encoded in Python logicEncoded in JS logic
Protocol enforcementCompile-time (Logtalk protocols)Runtime duck typingRuntime duck typing
PostgreSQL supportVia SWI-Prolog library(pgsql) / ODBCpsycopg2 (external)pg / node-postgres (external)
Backend portabilityMultiple Prolog systemsSingle runtimeSingle runtime
GDPR jurisdictionEU (Hetzner, Germany)EU (Hetzner, Germany)EU (Hetzner, Germany)
OriginPortugal πŸ‡΅πŸ‡Ή (EU), FCT-fundedUSA πŸ‡ΊπŸ‡ΈUSA πŸ‡ΊπŸ‡Έ

GDPR and Logtalk Backends

GDPR compliance for Logtalk services on sota.io:

Data residency. All data processed by your Logtalk service stays in Hetzner's German data centres. No automatic replication to US regions, no US Cloud Act exposure.

Declarative GDPR rules. GDPR obligations can be encoded directly as Logtalk rules: requires_consent(processing_purpose) :- not(legitimate_interest(processing_purpose)), not(legal_obligation(processing_purpose)). These rules are auditable, versioned, and can be tested with formal verification tools.

Minimal external dependencies. A Logtalk application running on SWI-Prolog with standard library predicates has a small, auditable dependency graph. For the EU Cyber Resilience Act's SBOM requirements, this minimises the compliance burden.

Protocol-based data access control. Logtalk protocols enforce that data access predicates implement proper access logging, consent checking, and erasure handling at the type level β€” the compiler reports missing implementations before deployment.

Audit trail by design. The gdpr_audit_category mixin pattern shown above makes GDPR Article 30 record-keeping composable: any object that imports the category gains audit logging without modifying its core logic.

Why sota.io for Logtalk

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 Logtalk service. Connection strings injected as environment variables. 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. Logtalk services deploy as Docker containers. SWI-Prolog is packaged in Debian's standard repositories (swi-prolog) and Logtalk is similarly packaged (logtalk). Auditable, reproducible builds.

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


Logtalk is an EU-origin language built by Paulo Moura πŸ‡΅πŸ‡Ή at the University of Beira Interior in Portugal, with FCT funding from Portugal's national research infrastructure. It brings formal object-oriented structure β€” protocols, categories, and encapsulated objects β€” to the declarative logic programming model of ISO Prolog, running on any standard Prolog backend from SWI-Prolog to SICStus. Its inherent explainability makes it a natural fit for EU AI Act compliance in high-risk AI domains: healthcare, credit, employment, and public administration. Its declarative rule encoding makes GDPR obligations auditable and formally verifiable. sota.io provides the EU infrastructure that Logtalk's Portuguese engineering heritage deserves β€” running in Germany, GDPR-compliant by default, managed so your team focuses on the knowledge.

Deploy your first Logtalk service to EU infrastructure β†’


See also: Deploy Prolog to Europe β€” SWI-Prolog HTTP backends on EU infrastructure, the ISO Prolog foundation that Logtalk compiles to Β· Deploy ECLiPSe CLP to Europe β€” EU constraint logic programming (ECRC Munich πŸ‡©πŸ‡ͺ, ESPRIT 1988); Logtalk runs on ECLiPSe as a Prolog backend, combining OOP structure with CLP(FD) constraint solving Β· Deploy Erlang to Europe β€” concurrent, fault-tolerant OTP backends (Ericsson πŸ‡ΈπŸ‡ͺ) with actor model Β· All languages on sota.io