Heimdall is a lightweight, pluggable data orchestration and job execution platform that abstracts complex data infrastructure from clients while offering a secure and consistent API for submitting and managing jobs.
Originally inspired by Netflix Genie, Heimdall extends the architecture to support:
- π Pluggable commands
- βοΈ Job queuing
- π‘ Synchronous and asynchronous execution
- π Sync & Async Job Execution
- π§© Plugin-Based Execution Framework: Shell, Glue, Snowflake, Spark, Trino, DynamoDB, and Ping
- π¬ REST API for programmatic access
- π Web UI for visual management
- π Secure orchestration without credential leakage
- π§ Dynamic routing based on command / cluster criteria
- π¦ Configurable or self-registering clusters
- π©Ί Cluster health checks with per-plugin probes and configurable timeout
Heimdall includes a web interface running alongside the API.
- API:
http://localhost:9090/api/v1 - Web UI:
http://localhost:9090/ui
git clone git@github.com:patterninc/heimdall.git
cd heimdallEnsure you have Docker or a compatible alternative installed.
docker compose up --build -dThis starts:
- The Heimdall server on port
9090 - The database and other dependencies
curl -X POST -H "X-Heimdall-User: test_user" -H "Content-Type: application/json" \
-d '{
"name": "ping-test",
"version": "0.0.1",
"context": {},
"command_criteria": ["type:ping"],
"cluster_criteria": ["type:localhost"]
}' \
http://127.0.0.1:9090/api/v1/jobUse the UI (http://127.0.0.1:9090/) or the following endpoints:
# Job status
GET /api/v1/job/<job_id>
# Job stdout
GET /api/v1/job/<job_id>/stdout
# Job stderr
GET /api/v1/job/<job_id>/stderrHeimdall supports a growing set of pluggable command types:
| Plugin | Description | Execution Mode |
|---|---|---|
ping |
Basic plugin used for testing | Sync or Async |
shell |
Shell command execution | Sync or Async |
glue |
Pulling Iceberg table metadata | Sync or Async |
dynamo |
DynamoDB read operation | Sync or Async |
snowflake |
Query execution in Snowflake | Async |
spark |
SparkSQL query execution on EMR on EKS | Async |
sparkeks |
SparkSQL query execution on EKS | Async |
trino |
Query execution in Trino | Async |
clickhouse |
Query execution in Clickhouse | Sync |
ecs fargate |
Task Deployment in ECS Fargate | Async |
postgres |
PostgreSQL query execution | Sync or Async |
Defines a reusable unit of work with associated tags and plugin logic.
An execution environment abstracted from its physical form. It can represent localhost, EMR, Kubernetes, a DB, a piece of your infrastructure that has context and a name, etc.
The orchestration request. It combines:
- Command criteria
- Cluster criteria
- Execution context
Heimdall dynamically selects the best command-cluster pair based on these criteria.
Initially, Commands and Clusters are configured via a static config file (see config.yml). Heimdall is evolving toward support for:
- Self-registering clusters
- Health-based routing
- API-based dynamic configuration
-
Commands: Must be active and match all tags in
command_criteria. -
Compatible Clusters: Found via the commandβs own
cluster_criteria. -
Final Selection:
- Filters clusters using the jobβs
cluster_criteria. - If multiple pairs match, one is selected randomly (a capability for custom "routing" is in works and will be represented as a plugin).
- If no match, the job fails with a detailed error.
- Filters clusters using the jobβs
Heimdall removes the need for:
- Embedding credentials in user environments
- Direct user and services access to infrastructure
It centralizes execution logic, logging, and auditingβall accessible via API or UI.
Commands may also restrict invocation via allowed_callers β a list of anchored regex patterns matched against X-Heimdall-User. Omitted/empty means open; non-matching callers are rejected at submit.
| Endpoint | Description |
|---|---|
POST /api/v1/job |
Submit a job |
GET /api/v1/job/<id> |
Get job details |
GET /api/v1/job/<id>/status |
Check job status |
POST /api/v1/job/<id>/cancel |
Cancel an async job |
GET /api/v1/job/<id>/stdout |
Get stdout for a completed job |
GET /api/v1/job/<id>/stderr |
Get stderr for a completed job |
GET /api/v1/job/<id>/result |
Get job's result |
GET /api/v1/jobs |
Get list of jobs |
PUT /api/v1/command/<id> |
Upsert command details |
GET /api/v1/command/<id> |
Get command details |
GET /api/v1/command/<id>/status |
Check command status |
PUT /api/v1/command/<id>/status |
Set command status |
GET /api/v1/commands |
List configured commands |
PUT /api/v1/cluster/<id> |
Upsert cluster details |
GET /api/v1/cluster/<id> |
Get cluster details |
GET /api/v1/cluster/<id>/status |
Check cluster status |
PUT /api/v1/cluster/<id>/status |
Set cluster status |
GET /api/v1/clusters |
List configured clusters |
GET /api/v1/clusters/health |
Health check all opted-in clusters |
GET /api/v1/cluster/<id>/health |
Health check a single cluster |
Opt any cluster into health probing by setting health_check: true in its config. Each plugin performs a lightweight connectivity check against its backend (see the Health Check column in the plugins table above).
Configure the global probe timeout (default 30s):
health_check:
timeout_seconds: 10GET /api/v1/clusters/health returns 200 if all probes pass, 503 if any fail. status per check: ok, error, or unchecked. Failing or misconfigured health checks have no effect on job execution or startup.
Surface extra links or text on a job in the UI with minimal change in plugin code - by declaring attributes on a cluster. Each attribute is a template that Heimdall renders after the job runs and stores in the job's job_attributes, which the UI then displays. Check local.yaml for the example.
Each entry is label β { kind, value }:
kindtells the UI how to rendervalue:link(clickable hyperlink) ortext.valueis a Gotext/templaterendered over four namespaces:.Jobβ the job object (e.g..Job.ID).Command/.Clusterβ the matched command's and cluster'scontextmaps.Outputsβ runtime values published by the plugin during execution
Static attributes (built only from .Job, .Command, .Cluster) need no plugin changes. For runtime-discovered values, a plugin publishes to the outputs channel with a single call - for example,
job.SetOutput("some_runtime_metadata", value)Heimdall was created at Pattern, Inc by Stan Babourine, with contributions from Will Graham, Gaurav Warale and Josh Diaz.