depth: 0%

0 — Surface

Axel Hoffmann

Building what runs
beneath the surface.

Backend engineer crafting distributed systems, IoT platforms, and the invisible infrastructure that makes things work. TypeScript, Rust, and everything in between.

Languages
RustTypeScriptJava
Frameworks
AdonisJSSpring BootActix-web
Data
PostgreSQLTimescaleDBRedisBullMQNATS JetStreamNGSI-LD
Infrastructure
ProxmoxDockerLoRaWAN
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

GET /ngsi-ld/v1/entities NGSI-LD

Query digital twin entities with NGSI-LD filtering

POST /api/v1/devices/provision LoRaWAN

Register a new LoRaWAN sensor on the network

POST /oauth2/token OAuth2

Issue access token via client credentials flow

PUT /api/v1/twins/:id/attributes REST

Update entity attributes with temporal context

GET /api/v1/metrics/campus REST

Aggregate sensor readings across campus zones

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.

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

9 packages, 4 dependency layers. Shared types, independent deployability, enforced boundaries via workspace constraints.

3 — Data

Data Layer

From external APIs to NGSI-LD entities. Collectors ingest, Harvesters transform, Redis caches, PostgreSQL persists — with BullMQ orchestrating the flow and presigned URLs for heavy assets.

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

9 Monorepo packages
4 Dependency layers
4 BullMQ queues
~60% Overhead reduction

Storage

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. Bare-metal servers, containerized services, encrypted tunnels, and the radio networks that connect sensors to the stack.

Proxmox

Hypervisor for VM provisioning. Automated templates, resource isolation, snapshot-based rollback.

Docker

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

LoRaWAN

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

4G/5G Backhaul

Cellular uplink for remote campus zones beyond wired reach. Failover routing, bandwidth 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.

Currently focused on distributed systems and digital twin platforms. I write Rust when performance matters, 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.