I work at the intersection of Elixir, Nix, category theory, systems engineering and enterprise architecture.
I tackle complex technical challenges by creating mathematically-grounded abstractions that reduce system complexity and accelerate innovation.
I help organizations rapidly prototype highly scalable systems and deploy them efficiently to production, turning technical challenges into competitive advantage.
Basic Applied Metamodeling - An upcoming book that provides a unique look at the abstract aspects of data modeling. It provides accessible exposition of algebraic property graphs and data integration, with a focus on simple diagrams and working code.
Paradigm - An open-source Elixir library for working with dynamic models and metamodels, with transformations and arbitrary levels of abstraction.
This core data modeling utility can be extended in many surprising directions to solve perennial problems of model-based software engineering (MBSE).
Nix: the Language, the Tool, the Package Repo, the OS
There’s a lot going on in the Nix ecosystem. If you haven’t slogged through the thesis then it might seem downright opaque. This is my attempt at an easy explainer for newcomers.
The Tool and the Language Let’s bootstrap ourselves with some circular facts.
Nix is a tool for building (or “packaging”) software components using instructions expressed in the Nix language. The Nix language is even able to package the Nix tool (which is mostly written in C++), thus closing the epistemological loop.
...
First Principles Infrastructure: Why NixOS Beats Containers and Clouds in 2025
In the marketplace of developer skills, there’s a certain category that I’m long-term bearish on. They don’t warrant investing free time trying to level up. Devs should limit their exposure to the minimum necessary to do their job. I’m talking about tools like Docker, Kubernetes, and the intricate managed hosting platforms of Azure and AWS. These are tools that help manage
social problems caused by scaling organizations to thousands of engineers existing complexity laziness or desire to throw money at a problem rather than solve it While they do solve real technical problems, I’ll argue here that there’s superior tooling for most use cases outside of big tech and legacy systems.
...
Three Tiers of Decoupling in Elixir
Allow me to weave you a tale of progressively stronger decoupling in Elixir.
I am working on a library that involves access to graph data, informed by a schema or model. Just to get things rolling I started out with a convention of holding graph nodes in a map:
map_graph = %{"node1" => %{"class_id" => "class1", "data" => %{ "testProp" => "value" }} %{"node2" => %{"class_id" => "class1", "data" => %{ "testProp" => "value2" }}} node = map_graph["node1"] value = node["data"]["testProp"] It’s quick, dirty, and gets the job done for proof-of-concept purposes. Clearly it’s inadequate for other data access patterns we’d like to be able to support. We can write transformation routines against this structure, but they won’t be able to work with anything else.
...
Superfluous Abstractions: The Landscape of LLM Tooling
Judging by the activity of marketing hypemen and growth hackers, it seems “Agents” are a Big Important Thing. I can’t scroll 2 posts on social media without being offered a course or a low-code service. As usual, the grifters are trailing the edge by a few years. If you try to pin down a definition, it seems to boil down to “a distributed, fault-tolerant software system… with LLM calls”. So that means we just need to throw Claude on the BEAM. Easy enough! For those willing to read some Elixir code I direct you to a pair of excellent blog posts from 2023:
...
The Power of Nix: Developing, Building, and Deploying a Phoenix App
The inordinate usefulness of Nix really sinks in when you realize that it allows you to define a single piece of unified infrastructure for handling all the different parts of the software lifecycle. Furthermore, this infrastructure doesn’t even need to be project-specific. For a given class of projects, the “holy grail” Nix flake template defines all the following:
All the dependencies, pinned in the flake.lock and updatable with nix flake update. A dev environment accessible with nix develop. A package derivation that encapsulates the build process in a nix build command. A module that exposes the app as a configurable system-level service that can be leveraged in integration checks with nix flake check. With these things in place, activities that traditionally create overhead for developers (environment and deployment) are abstracted and standardized. And even though other tools solve similar problems, none of them achieve the universality of the Nix model. That’s because the most natural and complete description of software packaging is as pure functions over store paths. But in this post I’m focusing on convenience. The correctness of Nix, and the fact that correctness leads to convenience, are topics for a different post.
...
Deploying Hugo in NixOS
While my instinct is to use Phoenix for everything, I had to admit it’s overkill for a personal website. I’m not here to flex complex backend integrations or live features. I’ve heard good things about Hugo, so maybe it’s time to try it. I will describe how Nix and deploy-rs allowed me to get framed out and deployed in one short and painless sitting!
A quick google search yielded a serviceable flake for a Hugo dev environment. So I just ran nix develop, hugo new site and then had a Claude agent throw in some placeholder content. 5 minutes later I had something serving on localhost.
...
Setting up deploy-rs for NixOS
Our starting point here is a node that is freshly infected with NixOS. For changing the system, we have 2 options.
SSH in and edit the configuration files (or copy them over) and then run nixos-rebuild switch which triggers the node to pull and build all the necessary items.
Check and build the configuration locally, and copy the entire closure across.
At a glance there might not be an advantage to one or the other. But consider if you’re deploying custom content that isn’t part of nixOS builtin configuration. To use method (1) you would need to clone all your repos on the server to be able to rebuild. Then every update requires you to ssh in and pull.
...
Provisioning a NixOS node in DigitalOcean
Here’s an easy way to get a NixOS node spun up using nixos-infect.
1) Set up a new droplet Choose Ubuntu 22.04 Add SSH keys for something you have a local IdentityFile for. Under “Advanced Options” -> “Add initialization scripts” paste #cloud-config write_files: - path: /etc/nixos/host.nix permissions: '0644' content: | {pkgs, ...}: { environment.systemPackages = with pkgs; [ vim ]; } runcmd: - curl https://raw.githubusercontent.com/elitak/nixos-infect/master/nixos-infect | PROVIDER=digitalocean NIXOS_IMPORT=./host.nix NIX_CHANNEL=nixos-25.05 bash 2>&1 | tee /tmp/infect.log 2) SSH in and copy config down Add the node’s SSH config to ~/.ssh/config
...