Skip to content

The Three Executables: utlx, utlxd, and utlxe

UTL-X is one language, but it ships as three separate executables. Each is built for a different stage of the development and deployment lifecycle. Understanding which to use — and when — is essential before diving into the language itself.

One Language, Three Runtimes

All three executables share the same core:

  • The same ANTLR-based parser (identical grammar, identical AST)

  • The same interpreter (identical expression evaluation)

  • The same Universal Data Model (identical type system)

  • The same 650+ standard library functions

  • The same 11 format parsers and serializers

  • The same 7 schema validators

A transformation that works in one executable works identically in all three. A bug fix in the shared core fixes all three simultaneously. This is by design — the conformance suite (500+ tests) validates behavior across executables.

The difference is in what surrounds the core: how input arrives, how output is delivered, and how the process is managed.

The three UTL-X executables — utlx (CLI tool), utlxd (IDE daemon), and utlxe (production engine). All share the same core; each targets a different use case.

utlx — The CLI

The command-line interface is for developers. It's the tool you install on your laptop, use in shell scripts, and run in CI/CD pipelines.

Lifecycle: single invocation. You run a command, it processes data, it exits. No persistent process, no state between runs.

Distribution: native binary (GraalVM) via Homebrew, Chocolatey, or direct download. Also available as a JVM JAR for development.

Key characteristics:

Startup time< 10ms (native),  250ms (JVM)
Memory40 MB (native),  150 MB (JVM)
Workers1 (single-threaded)
Protocolstdin / stdout / files
StrategiesTEMPLATE only
Hot reloadNo — each run is independent
MetricsNone
Best forDevelopment, scripting, CI/CD, one-off conversions

Modes:

  • Transform: utlx transform script.utlx input.xml — run a .utlx file against input data

  • Expression: echo data | utlx -e '.name' -r — inline one-liner, jq-style

  • Identity (flip): cat data.xml | utlx — auto-detect format, convert to the complement

  • REPL: utlx repl — interactive mode for experimentation

  • Validate: utlx validate script.utlx — check syntax without running

  • Functions: utlx functions --search date — browse the standard library

The CLI is covered in depth in Chapter 5.

utlxd — The Daemon

The daemon is the bridge between UTL-X and your IDE. It runs as a background process on your development machine, communicating with the VS Code extension via the Language Server Protocol (LSP).

Lifecycle: long-running. Starts when VS Code opens a .utlx file, stops when VS Code closes. Keeps the parsed state of your transformations in memory for instant feedback.

Distribution: JVM JAR only. The daemon needs full Kotlin reflection for language features like autocompletion and type inference — GraalVM native image doesn't support this yet.

Key characteristics:

Startup time1 second
Memory200 MB
Workers1 (serves one IDE session)
ProtocolLSP over stdio
StrategiesTEMPLATE only
Hot reloadYes — re-parses on every keystroke
MetricsNone
Best forVS Code extension, IDE integration

Features provided to the IDE:

  • Real-time diagnostics: syntax errors highlighted as you type — no need to save and run

  • Autocompletion: function names (all 650+), property paths (from parsed input), keywords

  • Hover information: function signatures, parameter types, return types

  • Live preview: transformation result updates as you type (with sample data)

  • Go-to-definition: navigate to function definitions and variable bindings

  • Format document: auto-indent and style your .utlx file

The daemon is not used in production — it's a developer tool. You never deploy utlxd to a server. The IDE chapter (Chapter 7) covers it in detail.

utlxe — The Engine

The engine is for production. It's a long-running transformation service that accepts messages via HTTP, gRPC, or message brokers, transforms them at high throughput, and returns results.

Lifecycle: long-running. Starts with the container, runs indefinitely. Transformations are loaded at startup or hot-reloaded via API.

Distribution: Docker image (ghcr.io/utlx-lang/utlxe). Available on Azure Marketplace as a managed application.

Key characteristics:

Startup time3 seconds (JVM)
Memory512 MB – 8 GB (configurable)
Workers8–128 concurrent threads
ProtocolHTTP REST (8085), gRPC, stdio-proto, stdio-json
StrategiesTEMPLATE, COPY, COMPILED, AUTO
Hot reloadYes — load/update/unload via HTTP API
MetricsPrometheus (port 8081)
Best forCloud deployment, Azure/GCP/AWS Marketplace

Transport modes:

  • --mode http — HTTP REST API on port 8085. The primary mode for cloud deployment. Endpoints: /api/transform, /api/load, /api/execute/\{id\}, /api/health

  • --mode grpc — gRPC service for low-latency, binary protocol communication

  • --mode stdio-proto — protobuf over stdin/stdout, used by the C# and Go wrappers

  • --mode stdio-json — line-delimited JSON over stdin/stdout, for backward compatibility

Execution strategies:

The engine offers four strategies that trade initialization time for runtime performance:

StrategyInit timeRuntimeBest for
TEMPLATEInstantInterprets ASTDevelopment, simple transforms
COPYFast (build skeleton)Clone + fillSchema-driven, predictable structure
COMPILEDSeconds at startup (one-time, before ready)JVM bytecodeMaximum throughput, complex logic
COPY + COMPILEDSeconds at startup (one-time, before ready)Clone skeleton + JVM bytecodeUltimate throughput: pre-built structure + compiled logic
AUTODependsDependsProduction default (schema → COPY, else → TEMPLATE)

COPY + COMPILED is not a separate strategy: value — it is what COPY does automatically: when you select COPY (or AUTO chooses it), the engine also compiles the fill logic to bytecode where it can, combining the pre-built skeleton with compiled expressions for the fastest path.

COMPILED strategy compiles UTL-X expressions to JVM bytecode using the ASM library — the same technology that Java itself uses. This achieves throughput of 86,000+ messages per second on a single instance with 8 workers. Chapter 32 covers the engine lifecycle (design-time, init-time, runtime) and Chapter 36 covers performance tuning.

Cloud deployment:

UTLXe is designed for containerized environments:

  • Azure Container Apps — available on Azure Marketplace (Starter $35/month, Professional $105/month)

  • GCP Cloud Run — Terraform module included, $44/month

  • AWS ECS/Fargate — CloudFormation template, $44/month

  • Any Kubernetes cluster — Docker image from ghcr.io

Chapter 33 covers cloud deployment in detail.

Comparison at a Glance

Aspectutlx (CLI)utlxd (Daemon)utlxe (Engine)
PurposeDevelopmentIDE integrationProduction
LifecycleSingle runLong-runningLong-running
RuntimeNative or JVMJVM onlyJVM (Docker)
Startup< 10ms1s3s
Workers118–128
Protocolstdin/stdoutLSPHTTP / gRPC / proto
StrategiesTEMPLATETEMPLATEAll four
Hot reloadNoYes (LSP)Yes (API)
MetricsNoneNonePrometheus
Distributionbrew / chocoVS Code extDocker / Marketplace
Branchmaindevelopmentdevelopment

The Wrapper Pattern

What if your application is written in C#, Go, or Python — not Kotlin/JVM? You don't need to rewrite UTL-X. Instead, you use a wrapper library that spawns UTLXe as a subprocess and communicates via protobuf:

The wrapper is 200–300 lines of thin client code. The engine — 100,000+ lines of transformation logic — exists once. All languages get identical behavior, verified by the same 500+ conformance tests.

Available wrappers:

LanguageStatusUse case
C# / .NETBuiltAzure Functions, ASP.NET, console apps
GoBuiltOpen-M controller, Go microservices
PythonPlannedData science, Django/Flask, AWS Lambda
Java / KotlinNative (no wrapper)Direct API — UTLXe IS JVM

Chapter 34 covers SDKs and wrappers in detail.

When to Use Which

I want to...Use
Write a transformationutlxd (VS Code) + utlx (to test)
Convert a file quicklyutlx (identity mode or -e)
Process files in a shell scriptutlx (native binary)
Validate syntax in CI/CDutlx validate
Deploy a transformation APIutlxe –mode http
Connect to Azure Service Busutlxe + Dapr sidecar
Embed in a C# applicationutlxe via C# wrapper
Embed in a Go serviceutlxe via Go wrapper
Run performance benchmarksutlxe –mode http with load testing

The typical developer workflow: write in VS Code (utlxd), test on the command line (utlx), deploy to production (utlxe). Same .utlx file at every stage.

Released under AGPL-3.0.