Author Image

Hi, I'm Wilhelm

I build the systems that keep operations running: automation, dashboards, and backend services.

Wilhelm Maritz

Backend & automation developer

I came to software the long way round. For years I worked in healthcare operations, where the margin for error was thin. Somewhere in there I started automating the parts that kept breaking, and the building never stopped.

These days the work is mostly backend: pulling messy data into something coherent, designing dashboards people actually use, and wiring up workflows that run without anyone babysitting them. The interesting problems are rarely the happy path. They are the edge cases and the failure modes.

It is one thing to make something work once; it is another to make it auditable, documented, and safe to hand over. A long stint working under operational pressure, plus a clinical and management background, taught me to design for the day things go wrong rather than the day they go right.

Right now I am going deep on backend development through the boot.dev track: Python, data structures and algorithms, Linux, and a bit of C for the memory-management fundamentals. I build to understand things from the ground up, and I would rather ship a practical solution than talk about one. On the side, I am chipping away at German.

Skills

Projects

Paul Newman Cup
Paul Newman Cup
Built and maintained 2026 to present

Purpose: an inter-team fitness and sports competition where teams score across four pillars.
Key features: Strava sync and verification for runs, rides, and swims, officials capturing monthly results, and role-controlled administration.
Stack: Flask, SQLAlchemy, SQLite in WAL mode, Firebase sign-in, Strava OAuth, on Railway behind gunicorn.

The design splits identity from permission: Firebase proves who you are, but the app’s own database decides what you can do, including an account kill-switch that takes effect on the very next request. Because the app is server-rendered, the session rides in a secure HttpOnly cookie rather than a bearer token, which would need client-side JavaScript to attach it to every request.

railway-bridge
Built and maintain 2026

Purpose: Railway shows a service’s requests, latency and resources in its dashboard but exports none of it, so a Flask app I maintain there was the one blank spot in my Grafana.
What it does: one Python file, standard library only, polls Railway’s GraphQL API every five minutes and serves Prometheus metrics: requests by status class as a real counter, latency percentiles, CPU, memory and disk against their limits, 7-day totals, and the last 20 deploys with their version and change.

The hard part was the counter. Railway hands back per-minute figures, the newest minute is still filling in, and polls overlap, so it keeps a high-water mark per status code and only counts a minute once it has ended. Checked against Railway’s own figures: 9,344 of 9,344 requests over 21 hours. Written up in Railway shows my request counts but won’t export them.

kuma-monitors
Built and maintain 2026

Purpose: Uptime Kuma has no config file, so monitors clicked into its web UI can’t be reviewed, diffed or rebuilt.
What it does: declares the monitors, groups, status page and ntfy notification in Python and creates them over Kuma’s API. It is safe to re-run: it matches by name and skips what already exists.

Its guard came from a real gap: Kuma’s “default” and “apply to existing” settings don’t attach a notification to monitors created later over the API, and for two days none of mine could alert. The script now attaches the notification to every monitor and refuses to finish while any monitor is left silent. Written up in The 03:37 alert that was never sent.

Connection health checker for Power Automate
Build and maintain 2025

A PowerShell tool that scans every environment in a Power Platform tenant and reports broken, expired, or soon-to-expire connections before they take flows down. For each unhealthy connection it maps the flows that depend on it, so you see the blast radius instead of a bare error list. The fiddly part was the mapping itself: a flow references its connection by an internal connectionName string rather than an id, so the tool resolves those references directly. Built on the Power Apps administration cmdlets, with retry logic and progress reporting for large tenants.

Flow failure checker for Power Automate
Build and maintain 2025

The incident-response companion to the connection health checker: a PowerShell script that sweeps all environments for flows that failed in the last 24 hours, or any window you give it, and produces a single failure report. It installs the administration modules it needs on first run, so it works from any admin workstation. Written for the boring but vital job of knowing every morning exactly what broke overnight.

Homelab
Build and run Ongoing

The NAS: a ZimaBoard 2 running ZimaOS, with a RAID1 mirror (2 x 4 TB, BTRFS) holding photos in Immich, documents in Paperless-ngx, backups and personal archives. Services are reached through Cloudflare Tunnels and Tailscale rather than open ports.
The server beside it: a GMKtec K10 running Proxmox VE on ZFS, with one VM for my AI agents, kept off the NAS, and one for services: Grafana and Prometheus, fed by exporters I wrote, and Portainer. The VMs back up nightly to the mirror, and I restored one before trusting the backups.
Watching it: Uptime Kuma, declared in code, alerts my phone through ntfy.

The sharpest lessons have come from storage: a migration once filled the system disk and left the storage layer unable to cleanly reattach the array, which taught me to treat the OS as disposable and the data as authoritative, and to rebuild from a verified backup rather than chase a half-recovered state.

Property analytics workbook
Personal project Ongoing

A spreadsheet model for analysing residential buy-to-let investments across financing, cash flow, and tax treatment, used to compare prospective deals on a consistent basis. Built in Excel and Google Sheets.

Posts