0 — Surface

Axel
Hoffmann

Backend Engineer

STARI — ULB & FARI · Brussels · 2023 — present

Distributed systems, IoT platforms, and the invisible infrastructure that makes things work.

Languages
RustTypeScriptPHPSQL
Backend
AxumTokioAdonisJSLaravel
Data & Messaging
PostgreSQLTimescaleDBNATS JetStreamMQTTRedisNGSI-LD
Infrastructure
Kubernetes / OKDGitOpsDockerProxmoxLoRaWAN
scroll to descend

1 — Interface

APIs & Protocols

The contracts that connect systems. REST endpoints, NGSI-LD for digital twins, LoRaWAN device provisioning, OAuth2 flows — every interaction starts at the interface.

Endpoints

Illustrative — representative of the APIs I build, not a public reference
GET /ngsi-ld/v1/entities NGSI-LD

Query digital twin entities with NGSI-LD filtering

POST /api/v1/ingest/lorawan LoRaWAN

ChirpStack uplink webhook — idempotent ingestion into NATS JetStream

GET /api/v1/sensors/:id/timeseries REST

Time-series readings served from TimescaleDB continuous aggregates

POST /oauth2/token OIDC

OIDC token endpoint — RS256-signed JWTs, validated via JWKS

GET /api/v1/mobility/flows REST

Mobility data unified by the gateway for 3D visualization

DELETE /api/v1/subscriptions/:id NGSI-LD

Remove a real-time notification subscription

NGSI-LD

Context-based entity API for digital twin interoperability

LoRaWAN

Long-range IoT protocol for low-power sensor networks

OAuth2

Token-based authentication with client credentials and PKCE

MQTT

Lightweight pub/sub messaging for real-time sensor data

2 — Services

Services & Patterns

Where business logic lives. Domain-driven services, clean dependency boundaries, and architectural patterns that keep complexity in check.

Also in Production

Infofin infofin.ulb.be

Laravel platform delivered and running in production at ULB.

PHPLaravel
Tandem

Language-exchange platform matching learners for tandem practice.

TypeScriptAdonisJS
IRIS

Application submission platform handling candidate files end-to-end.

TypeScriptAdonisJS

Architecture Patterns

DI / IoC

Dependency injection and inversion of control for testable, decoupled service layers. Constructor injection, interface-driven contracts.

Event-Driven

BullMQ workers processing async jobs — sensor data ingestion, entity updates, notification dispatch. Decoupled producers and consumers.

CQRS

Command-Query Responsibility Segregation separating write paths (entity mutations) from read paths (optimized queries, cached views).

Monorepo

Layered workspaces with shared types, independent deployability, and dependency boundaries enforced by workspace constraints.

3 — Data

Data Layer

From sensor frames and external APIs to queryable entities. Idempotent multi-protocol ingestion on NATS JetStream with a dead-letter queue, time-series in TimescaleDB hypertables — and a BullMQ-orchestrated pipeline turning collected data into NGSI-LD entities.

Pipeline

01

Collect

Scheduled Collectors fetch data from external APIs and IoT sources

Cron / Collectors
02

Queue

Jobs dispatched across 4 priority queues for async processing

BullMQ / Redis
03

Process

Harvesters aggregate and transform collected data into new datasets

Harvesters / EventBus
04

Store

Metadata and historical data persisted, raw files on S3-compatible storage

PostgreSQL / OVH S3
05

Cache

Entity last-state and active subscriptions cached for sub-ms reads

Redis
06

Serve

NGSI-LD API exposes entities with subscription-driven real-time notifications

NGSI-LD / REST

At Scale

673 Automated tests
8 Rust crates
3 Ingestion protocols
4 BullMQ queues

Storage

TimescaleDB

Sensor time-series: hypertables, continuous aggregates, native compression

NATS JetStream

Durable event streaming for ingestion — idempotent consumers, dead-letter queue

PostgreSQL

Metadata, user ownership, subscriptions, historical entity data

Redis

Entity last-state cache, subscription cache, BullMQ queues, pub/sub

BullMQ

4 priority queues — collectors, harvesters, priority jobs, uploads

OVH S3

Raw files, 3D assets, tilesets — presigned URL upload for large files

4 — Infrastructure

Infrastructure

The physical and virtual substrate — and the pipeline that ships to it. Two substrates: a Proxmox VM running the SPARC backend under Docker, and an OKD/OpenShift cluster running everything else behind a full GitOps chain where merging to main is the deployment.

GitOps Chain

  1. Merge

    A merge on main is the only deployment trigger

  2. Tekton

    In-cluster pipelines build and push the images

  3. Argo CD

    Syncs cluster state to the Git repository, continuously

  4. Kustomize

    Per-environment overlays, no templating drift

  5. Sealed Secrets

    Secrets encrypted at rest in Git, decrypted only in-cluster

Kubernetes / OKD

Hardened workloads: readOnlyRootFilesystem, non-root containers, OpenShift SCC-constrained pods.

Docker

Containerized microservices with multi-stage builds. Compose for local dev, orchestrated deploys for production.

Proxmox

Runs the SPARC backend stack under Docker: Rust API, NATS, TimescaleDB, ChirpStack, Traefik. Event-driven TLS cert rotation, LoRaWAN chain secured gateway-to-network-server.

LoRaWAN

Long-range IoT gateway network. Payload decoding, device provisioning, sensor fleet management.

5 — Core

Core

I build the systems that run behind the screen — backend services, data pipelines, IoT infrastructure. I care about clean architecture, honest engineering, and making things that actually work under load.

Since 2023 I'm a backend engineer at STARI (ULB & FARI) in Brussels, in the orbit of FARI — the AI Institute for the Common Good. Distributed systems, digital twins, and IoT platforms in production. I write Rust when correctness and performance matter, TypeScript when velocity matters, and I'm always looking for the right tradeoff between the two.

Values

Depth over breadth

I'd rather understand one system deeply than skim ten frameworks.

Own the outcome

From schema design to deployment pipeline — I ship end-to-end.

Simple until proven otherwise

No premature abstractions. Complexity is earned, not assumed.

Beyond the Stack

With the FARI AI Academy, I delivered a one-day training on AI for the common good to BELSPO, the Belgian federal science policy office.