Skip to content
> andrew_dryga
Projects
Blitz
Single-handedly owned ~20 high-traffic backends end-to-end (77 Elixir umbrella apps, 70+ Redis/50+ PostgreSQL instances) serving ~25k RPS with peaks to 150k for a 7-figure DAU product.
Firezone
WireGuard-based replacement for legacy VPNs. Re-architected and developed key components of the enterprise product. Led infrastructure as code with Terraform on GCP. Open source, YC W22.
eHealth: National Health Service of Ukraine
Co-designed and built the national platform behind reimbursements, EMR, e-prescriptions, and nationwide APIs for clinics and pharmacies. Led architecture, security, hiring, and hands-on Elixir + DevOps. All development open-sourced under Apache license.
Hammer Corp
Advertising platform for thousands of US automotive dealerships: ingests inventory, syndicates ads to major channels (at peak accountable for 30%+ cars on Facebook Marketplace), measures conversion, and collects leads to a unified interface with 24/7 human first-responder reps answering within 60 seconds.
Ryker
A self-hosted AI teammate for engineering and on-call work. Ask in Slack or GitHub, share an alert, or give it a coding task. Ryker investigates, shows what it found, and keeps working as you follow up.
Emisar
Gives AI agents a reviewed catalog of infrastructure actions over MCP. Policy decides which requests run, need approval or are denied. Typed inputs, checks on the host and searchable run records let an agent keep working within the access you intended.
co:op
A runtime and orchestrator for coding agents. Run Claude, Codex or Gemini in a container, limit the project files and network access it receives, and work through a task queue in a separate fork you can review.
Offloader
Serves repeated product queries from published Parquet snapshots through declared REST endpoints. DuckDB runs on your infrastructure; your data pipeline owns the exports. It fits customer-facing reads that can tolerate the snapshot's age.
Bullpen - Virtual Sales Floor + CRM
When COVID hit, our sales team lost the buzz of the office. We built a platform that brought it back - a CRM with virtual space where reps could collaborate, learn from each other in real time, and keep the same drive. Then we turned it into a standalone product with AI sprinkled around it.
TalkInto - Omnichannel Messaging Platform and CRM
Messaging/voice backbone powering products like Hammer, Bullpen, and Text2Buy: SMS, voice, various chat integrations, and web chat with clean agent UI and APIs. Features included local numbers, call recording, and routing.
Contractbook
Built the self-service billing system, B2B API and marketing pipeline that kicked off the business growth.
Financial P2P Marketplace
Architecture and implementation for an institutional P2P lending marketplace for one of Europe's largest lenders ($9B portfolio).
Mbill - P2P Transfers
P2P transfer service for individuals and small-to-medium online merchants. Create a page for your card and share a link to receive payments. Includes customer cabinet, payment button constructor, and transaction reports.
Mastercard MoneySend
Front-end application to receive P2P transfers sent via recipient phone number. Country-wide rollout of phone-number-based transfers.
Forza - PayDay Loan Websites
Front-end, SMS gateway, decision engine, and marketing tools for an online lending originator operating in Moldova, Bosnia, and North Macedonia.
Best Wallet (ex. MBank)
eWallet cloud for worldwide money transfers. For B2C: pay for 2,700+ services across CIS, send money to phone numbers, cash out via partnered banks or cards. For B2B: free SaaS white-label eWallets for banks with simple integration.
IPSP.com - Payment Pages
Responsive landing and payment pages for an Internet Payment Service Provider. Improved conversion on payment flows via lighter UI.
ECommPay - Mobile App
iOS and Android business application for partners to manage payment platform on the go.
Autopayment
Automatically pays for bills based on two types of rules: by threshold of supplier balance (e.g., mobile top-up) or on a periodic basis.
Mobile Cashier
Turns Android devices into payment terminals for deposits and top-ups across numerous service providers, from cellular carriers to credit card loan repayments.
OnlyTTY
Share a shell or a single command through a link and control it from a browser or phone. Terminal traffic is end-to-end encrypted, and the relay never sees the session keys.
Sage - Sagas Pattern in Elixir
Dependency-free implementation of the Sagas pattern for distributed transactions with explicit compensation. Guarantees that either all transactions complete successfully, or compensating transactions amend partial execution.
LoggerJSON
Structured JSON logging for Elixir with first-class formatters for Google Cloud Logging, Datadog, and Elastic (ECS). Drop-in :logger formatter/handler with runtime config helpers.
Confex
Runtime configuration from environment variables with type casting and adapters (:system, :system_file). 12-factor friendly configuration for Elixir applications.
Elixir Bench
Continuous benchmarking platform for the Elixir ecosystem. Automatically runs performance benchmarks on each commit to detect regressions and track language performance improvements over time. Won Spawnfest 2017 and later accepted into Google Summer of Code.
Annon API Gateway
Configurable API gateway acting as a reverse proxy with a plugin system (ACL, Auth, Validation, CORS, Idempotency), request/response storage, metrics, management UI, and auth provider. Reduces boilerplate across services.
Ecto Mnesia Adapter
Ecto adapter for OTP's built-in Mnesia database that works in the same memory space as the application, providing extremely low latency without deploying a separate database.
Gandalf - Decision Engine
Open-source decision engine SaaS for rule tables, champion/challenger split testing, revision history, decision analytics, and debugging tools.
Man - Template Rendering Engine
Stores iex, mustache, or markdown templates and renders them with localization to HTML or PDF via REST JSON API. Includes an easy-to-use management UI. Free one-click deployment to Heroku.
Vagrant Box OS X
macOS Vagrant boxes for VirtualBox. Run UX tests or build iOS/Mac applications on any machine with a few CLI commands. Used by many teams worldwide, including Boxen. Got a $50k S3 bill in month one, was sponsored by Cloudflare for a while, and eventually taken down over Apple licensing.
Parasport - Foundation Portal
Medium-sized web portal for a foundation supporting Paralympic sport, physical rehabilitation, and social adaptation. Built on October CMS.
OneDayOfMine
Storytelling social network that helps see other people's lives through their eyes. Capture moments through the day and share them with descriptions - from special forces in Belarus to a family visit to a film museum in South Korea.
L15 - Night Club x Coworking
Experimental mix of coworking space and a night club ('clubworking') in Kyiv. Turned the office into a best-in-class night club and ran terrace events with world-class DJs every weekend for an entire summer.
Happy Customer
Outsource project to motivate small and medium-sized businesses to provide better customer service via public feedback and simple tracking.
truBrain 1.0
An early-stage product that needed help. I took some swings at UX and performance for free because I wanted to see them make it.
Blog
Your data warehouse is the wrong place to serve a dashboard
Customer-facing dashboards ask the same few questions all day, on data that's fine a few minutes stale - but every page load runs a live query against a warehouse that bills per query and was never built to sit behind a live screen. Here's the serving layer I built to move those reads onto cheap snapshots on my own infra.
Treating physical servers like cloud VMs
Modern BMCs turned bare metal into something you can terraform apply: declare a node in git, reimage it over the network, verify it against a receipt. How our cloud-to-on-prem migration kept the cloud workflow - and why that's exactly what LLM agents needed.
Your AI is brilliant. And blind
AI agents got good at writing code - and they're still flying blind on your infrastructure, guessing at problems they can't see. The obvious fix is to hand them SSH and let them run wild. Here's why I didn't, and what I built instead.
One brain, two agents: an OS for autonomous coding agents
AI agents lose context, stop early, and skip work. The fix is not a smarter prompt. It is a small, file-based operating system: a queue they cannot abandon, hooks they cannot ignore, and one shared source of truth.
Running an AI coding agent you can't trust
You can't trust an AI coding agent, and you shouldn't have to. Put it in a sandbox where the worst case is boring: one repo damaged, no secrets exposed, and a VM you can rebuild in a minute.
Design APIs with CDN in mind
Most APIs are designed for developer convenience, not cacheability. A few structural changes can make CDN do the heavy lifting for you.
The Real 10x Engineer
The real multiplier in software isn’t writing more code. It’s judgment: choosing the right problems, avoiding unnecessary systems, and reducing the maintenance burden that slows teams down.
Introducing Sage - a Sagas pattern implementation in Elixir
Distributed transactions are hard and expensive, if you wonder how to pragmatically handle them in a mid-size project - this article is for you.
Run stale tests on file change in Elixir
Mix is an awesome tool but most Elixir beginners are not aware of all its features. mix test --stale is one of them and can make your workflow much better.
Runtime configuration, migrations and deployment for Elixir applications
Shortly after moving from PHP to Elixir I've faced a common issue, the way we deploy applications is totally different from the one I'm used to.
National Health Service, on Elixir and Kubernetes
A look at building Ukraine’s national-scale eHealth platform with Elixir, Kubernetes, and pragmatic architecture for reliability and scale.
Bringing blockchain properties to centralized government databases
Making it cryptographically impossible to alter records in a database even with full system access.
Alternative approach for sensitive file uploads
Using signed URLs for secure file uploads directly to cloud storage, bypassing your application servers entirely.
Designing a P2P Lending platform with Elixir in mind
With this post, I want to share with you the design process on one of our latest projects - a P2P marketplace that was intended to be used by hundreds of thousands of users.
$ cat ./blog/untrusted-ai-coding-agent

Running an AI coding agent you can't trust.

I was a vibe-coding skeptic for a long time. Recently the models got good enough that I actually trust them to do what I want - under pretty pedantic supervision, but still.

And isn’t it annoying? You finally have something that can do the work for you, and you’re still stuck at the computer babysitting every approval it asks for.

I want it to just work so I can go focus on something else, without being interrupted every ten minutes. But I work on a lot of sensitive infrastructure, so I can’t run these things in YOLO mode either. I genuinely don’t enjoy the little adrenaline hit I get every time I let even the best model run unattended, knowing it can hallucinate its way into dropping a production database.

By default you get one of two extremes. Either the agent asks permission for everything and you spend the day as a human OK-button, or you pass --dangerously-skip-permissions and hand a shell on your laptop to a stochastic process.

It’s safe but useless, or useful but terrifying. At least for me.

Some people frame this as a trust problem: can I trust the model? Wrong question. You can’t, and you shouldn’t have to. Trust is not a property of the model. It’s a property of the system around it. Put the agent in a box where the worst thing it can do is cheap to undo, and whether you trust the model stops mattering.

This article builds that box. A follow-up - an OS for autonomous coding agents - is about what you do once you have it: leave it running for hours without babysitting it. You need the box first.

One shortcut before we start: I packaged this whole setup as a single Go binary, coop. If you just want the box and not the theory:

curl -fsSL https://raw.githubusercontent.com/AndrewDryga/coop/main/install.sh | sh

Implementation update, October 2026: the shell examples below explain the original design. Current co:op uses Docker for online provider sessions and a per-run credential broker; the Apple container example is not its current setup procedure. Use the sandbox walkthrough to check files, credentials and networking, then the overnight task walkthrough for a separate fork and a reviewable queue. Known secret-path filtering still needs your project’s exclusions; it cannot recognize every credential embedded in ordinary source.

The rest of this article develops the design as plain shell so the boundaries are visible. Treat the examples as a design walkthrough, not a copy of the current launcher.

Trust the sandbox, not the model

Here’s the thing about how agents fail: it’s almost never malice. It’s statistics. An rm -rf where a variable expanded to the wrong path. A helpful git push --force because the remote “looked stale”. Your .env pasted into a bug report because the agent wanted to show you the failing config. Ask around - everyone has a story.

You’re not going to fix that with prompting. “Please be careful” is not a security boundary. The fix is the oldest idea in the book: least privilege, enforced by something the agent can’t talk its way around. The agent should see exactly one thing - the repo it’s working on. Not your home directory, not your SSH keys, not your browser profile, not the rest of your disk.

“But don’t the CLIs sandbox themselves now?” They do, and the built-in sandboxes are genuinely useful - Claude Code’s /sandbox wraps bash in Seatbelt on macOS and bubblewrap on Linux, Gemini CLI ships the same idea with configurable profiles. Turn them on. They’re free.

But read the fine print before you bet an unattended run on one. Claude Code’s sandbox blocks writes outside the working directory - but reads of your entire disk, ~/.ssh and ~/.aws/credentials included, are allowed by default until you go and deny-list them yourself. So nothing actually stops the agent from SSHing into production to “investigate” something and breaking it. And if you use Tailscale SSH or Teleport, it’s worse - the model can reach your whole fleet through them, and you might not even notice it happened.

The sandbox also only covers bash subprocesses - not the harness itself, not the other tools. And every developer-friendly sandbox ships escape hatches on purpose: a retry-outside-the-sandbox flag, an excluded-commands list, a documented “if it gets in your way, turn it off” toggle. All of that is reasonable for interactive use, when you’re sitting there watching. But for eight unattended hours I want the opposite default: nothing readable, nothing reachable, unless I explicitly put it there. That’s a VM.

Anthropic basically says this themselves - their docs recommend running --dangerously-skip-permissions only inside an isolated container. So let’s build one.

A VM with one door

On a Mac, the nicest option right now is Apple’s container. It’s open source, written in Swift, and runs every container as its own lightweight VM on Apple silicon - a real hypervisor boundary instead of a shared kernel, and it still boots in about a second. It needs macOS 26 and installs from a signed package on the releases page. On Docker or Podman everything below works the same; only the flags change.

The image is four lines:

FROM node:22
RUN npm install -g @anthropic-ai/claude-code
USER node
WORKDIR /workspace

That USER node matters. Claude Code refuses to skip permissions as root - one of the rare cases where a tool protects you from yourself - so run as the unprivileged user the base image already ships.

Build it and start an agent:

container system start
container build -t agent-box .

container run -it \
  -v "$HOME/projects/myapp:/workspace" \
  -v claude-home:/home/node/.claude \
  agent-box \
  claude --dangerously-skip-permissions

Two mounts, each doing one job:

  • The repo is bind-mounted at /workspace. That’s the door. The agent edits real files, and you see the changes in your editor instantly.
  • claude-home is a named volume so you log in once and your credentials survive restarts. Prefer not to? Skip it and pass ANTHROPIC_API_KEY instead.

Now do the honest thing and walk through the worst case - it’s the only real way to judge a sandbox. The agent loses its mind and runs rm -rf /. What actually dies? A VM that rebuilds from a four-line Dockerfile, and the working copy of one repo - which is a git clone and a reflog away from coming back. Your OS isn’t reachable. Your home directory isn’t mounted. The blast radius is a directory you can restore in a minute.

Want it even tighter? Don’t mount anything. git clone inside the container and let the agent work on the copy. Now git is the only door between the agent and your world. I find the bind mount more practical day to day, but the clone is the right default for anything you’d call risky - and it closes the secret problem for free, which we’ll get to.

One hole first, though: that bind mount carried the whole repo into the VM - .env and all. Let’s close it.

Keeping secrets out of reach

“Give it the repo” almost always means “give it the repo except a few files”: .env, secrets/, deploy keys, terraform.tfvars, *.tfstate.

You’d think there’s a setting for this. There isn’t. The built-in sandboxes and the popular Seatbelt wrappers guard secrets in your home directory and leave a nested project/.env perfectly readable - masking secrets inside the working tree is a gap every tool I tried leaves to you. So we close it ourselves.

There are two layers here, and they’re not equally strong. The strong one is the filesystem. A path that was never mounted into the VM simply can’t be read by anything inside it - not the file tools, not a clever bash one-liner, not a little python script the agent writes to “debug the config”. The bytes aren’t there.

You could shadow those paths by hand, one --tmpfs flag at a time. But that’s a demo, not a policy - it depends on you remembering every secret in every repo, every single time, and it breaks the first time you forget one. So let the launcher find them for you. Mine matches known names and extensions:

#!/bin/bash
# bin/agent - start a sandboxed agent; secrets never enter the VM
set -euo pipefail

repo="$(git rev-parse --show-toplevel)"

# Anything matching these never enters the VM.
secrets=(
  '.env' '.env.*' '*.secret' '*.secrets'
  '*.tfvars' '*.tfstate' '*.tfstate.*'
  '*.pem' '*.key' '*.p12' '*.pfx' '*.jks'
  'id_rsa*' 'id_ed25519*' 'id_ecdsa*'
  '.netrc' '.npmrc' '.pypirc' '.git-credentials'
  'secrets' '.secrets' 'credentials' '.aws' '.kube' '.ssh' '.gnupg'
)
# Templates are fine to show the agent.
allow=('*.example' '*.sample' '*.template')

match=(-name "${secrets[0]}")
for n in "${secrets[@]:1}"; do match+=(-o -name "$n"); done
skip=()
for n in "${allow[@]}"; do skip+=(! -name "$n"); done

decoy="$(mktemp)"
mounts=(-v "$repo:/workspace")
count=0

while IFS= read -r -d '' path; do
  rel="${path#"$repo"/}"
  if [ -d "$path" ]; then
    mounts+=(--tmpfs "/workspace/$rel")
  else
    mounts+=(-v "$decoy:/workspace/$rel:ro")
  fi
  count=$((count + 1))
done < <(find "$repo" -name .git -prune -o \( "${match[@]}" \) "${skip[@]}" -print0 -prune)

echo "shadowed $count secret paths" >&2

# Assemble the whole run as one array, then expand it once.
run=(run --rm)
[ -t 0 ] && run+=(-it)          # a tty only when we have one; headless runs skip it
run+=("${mounts[@]}" -v claude-home:/home/node/.claude agent-box)
exec container "${run[@]}" claude --dangerously-skip-permissions "$@"

(On Docker, replace container with docker - the flags are identical.)

The mechanics are simple. Directories on the list get an empty tmpfs mounted over them, so inside the VM the path exists but is empty. Files get a read-only empty decoy on top, so cat /workspace/.env returns nothing and writing to it fails. find lists parents before children, so a secrets/ tmpfs always lands before any decoy inside it. And the allow list handles the obvious false positive - .env.example is documentation, the agent should see it.

Then verify it the way you verify any security control: try to break it. Drop SECRET=hunter2 into .env, start the agent, and ask it to print the file any way it can. I did exactly that before writing this section - cat, dd, reading it from a script - and inside the VM every road leads to an empty file, and the write attempt dies with “Read-only file system”.

One honest limit before you lean on this: find runs once, at launch. It shadows what’s on disk the moment the agent starts - it can’t see a secret that shows up later, like a git pull that drags in a tracked config file, or a build step that writes a fresh secrets/ halfway through the run. For a live working tree, that’s the price of watching the agent’s edits land in your editor in real time.

Keep Claude Code’s deny rules as a second layer, mirroring the same list in .claude/settings.json:

{
  "permissions": {
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)",
      "Read(./**/*.tfvars)",
      "Read(./**/*.pem)"
    ]
  }
}

But be honest about the order of trust here. Deny rules stop the polite tools - they’re great at keeping the agent from accidentally pulling config into its context and leaking it into a commit message. They are not the boundary. A deny rule stops the Read tool, not a creative shell command. If the bytes are in the mount and only a deny rule guards them, assume a long enough session finds them. The mounts are the lock; the deny rules are the “please don’t” sign you put up anyway.

Which leads to the boring conclusion: secrets shouldn’t live in the repo directory at all. Load them from outside - direnv, 1Password, whatever you already use - and the whole problem just disappears.

And one disclaimer - maybe the most important paragraph in this article: a sandbox limits blast radius, it doesn’t guarantee containment. If OpenAI, with all its resources, couldn’t stop its own models from escaping an eval sandbox and hacking Hugging Face, you shouldn’t count on your own sandbox doing it either.

The filesystem boundary we’ve built decides what the agent can damage, and we’ve locked that down hard. It says much less about what the agent can send. A coding agent still has to reach the model endpoint to work at all, so the network is never fully off. Which means if it reads a malicious repo and gets prompt-injected, anything still readable inside the VM can leave over that same connection - including the Claude credentials in the claude-home volume, which Anthropic’s own dev-container docs warn a hostile project can lift.

You can tighten the network side too - put a filtering proxy in front of the box (Squid, say) and whitelist the handful of hosts the agent is allowed to reach.

There is a real security tradeoff here, though. If you restrict egress too much, the model can’t curl documentation anymore, and it can’t do its job. So I tend to allow egress, accept that the agent could leak the source code, and make sure the only credential it can reach is the LLM API token.

The safest handoff: give it a clone

The launcher shadows secrets out of a tree you still own. The cleaner move is to never hand over the real tree at all. Give the agent a throwaway clone:

git clone . ../myapp-agent

Two nice things fall out of that one command, both for free.

The clone has no secrets in it. git clone only copies committed state, and your real secrets - .env, secrets/, tfvars - are gitignored, so they never make it into the clone. A gitignored .env can’t reappear, because it was never committed: nothing to enumerate, nothing for a mid-session git pull to drag back in.

Run the shadow launcher on the clone too, for anything secret-shaped that is tracked. And if a real secret made it into git history at some point, no mount will save you - it’s one git show away. That’s not a sandbox problem. You have to rotate your keys.

The agent has nowhere to push. A local clone’s origin is a filesystem path that only exists on the host - inside the VM it points at nothing. No GitHub token, no ~/.ssh, no .gitconfig is ever mounted. The agent gets full local git - branches, commits, history, everything it actually needs - and the work only comes back when you pull it, from the host:

git fetch ../myapp-agent agent-branch:review/agent
git diff main...review/agent

You review the branch like a contractor’s PR, merge what’s good, and delete the directory. The agent never touched your remotes, never saw your credentials, never had a way off the machine that you didn’t walk yourself.

But my project needs a database

So far the box is a four-line image: Node and one CLI. But real-world projects need more than that. Most of my apps, for example, are written in Elixir and talk to Postgres and Redis.

Can’t the agent just install what it needs? It can try, and it will fail. It runs as a non-root user (Claude won’t skip permissions any other way), the container gets thrown away on exit (every run starts from scratch), and “let the agent apt-get whatever it wants” is exactly how you end up with an environment nobody can reproduce. Installing at runtime is the wrong move. Bake the dependencies into the container image itself.

Put the toolchain in the image. Switch to FROM elixir:1.18 instead of FROM node:22, add the agent CLI on top, build once. Prompt the agent to edit the Dockerfile whenever it hits a missing system package, and carefully review those changes before merging them. And keep build caches (hex, npm, whatever) in a named volume so a fresh disposable container still starts fast.

Put the stateful services on a shared network. Postgres and Redis can run in their own containers, and the sandbox can reach them by name. All the agent container needs is a DATABASE_URL=postgres://postgres:postgres@db:5432/app_dev environment variable. The most convenient way to do this is with docker compose.

So, can you trust it?

No, and we don’t have to. Nothing here requires you to trust the model. The container doesn’t trust it with your machine. The mounts don’t trust it with your secrets. The clone doesn’t trust it with your remotes. And precisely because nothing trusts it, you can finally stop hovering.

So stop asking “can I trust the agent?” and start asking “what’s the worst this system lets it do?” When the honest answer is “lose one commit of work inside a VM I can rebuild in a minute” - the fear just goes away, and you’ve got a box that’s safe to walk away from.

And walking away is the next part we should build. An agent that can’t wreck your laptop is still an agent that loses its context, stops before the job’s done, and quietly skips half of it. Turning this safe box into something that runs your repo for eight hours straight - and actually finishes every task - is the next article: an OS for autonomous coding agents.

Related Projects

co:op

A runtime and orchestrator for coding agents. Run Claude, Codex or Gemini in a container, limit the project files and network access it receives, and work through a task queue in a separate fork you can review.

View project →
Projects
Blitz
Single-handedly owned ~20 high-traffic backends end-to-end (77 Elixir umbrella apps, 70+ Redis/50+ PostgreSQL instances) serving ~25k RPS with peaks to 150k for a 7-figure DAU product.
Firezone
WireGuard-based replacement for legacy VPNs. Re-architected and developed key components of the enterprise product. Led infrastructure as code with Terraform on GCP. Open source, YC W22.
eHealth: National Health Service of Ukraine
Co-designed and built the national platform behind reimbursements, EMR, e-prescriptions, and nationwide APIs for clinics and pharmacies. Led architecture, security, hiring, and hands-on Elixir + DevOps. All development open-sourced under Apache license.
Hammer Corp
Advertising platform for thousands of US automotive dealerships: ingests inventory, syndicates ads to major channels (at peak accountable for 30%+ cars on Facebook Marketplace), measures conversion, and collects leads to a unified interface with 24/7 human first-responder reps answering within 60 seconds.
Ryker
A self-hosted AI teammate for engineering and on-call work. Ask in Slack or GitHub, share an alert, or give it a coding task. Ryker investigates, shows what it found, and keeps working as you follow up.
Emisar
Gives AI agents a reviewed catalog of infrastructure actions over MCP. Policy decides which requests run, need approval or are denied. Typed inputs, checks on the host and searchable run records let an agent keep working within the access you intended.
co:op
A runtime and orchestrator for coding agents. Run Claude, Codex or Gemini in a container, limit the project files and network access it receives, and work through a task queue in a separate fork you can review.
Offloader
Serves repeated product queries from published Parquet snapshots through declared REST endpoints. DuckDB runs on your infrastructure; your data pipeline owns the exports. It fits customer-facing reads that can tolerate the snapshot's age.
Bullpen - Virtual Sales Floor + CRM
When COVID hit, our sales team lost the buzz of the office. We built a platform that brought it back - a CRM with virtual space where reps could collaborate, learn from each other in real time, and keep the same drive. Then we turned it into a standalone product with AI sprinkled around it.
TalkInto - Omnichannel Messaging Platform and CRM
Messaging/voice backbone powering products like Hammer, Bullpen, and Text2Buy: SMS, voice, various chat integrations, and web chat with clean agent UI and APIs. Features included local numbers, call recording, and routing.
Contractbook
Built the self-service billing system, B2B API and marketing pipeline that kicked off the business growth.
Financial P2P Marketplace
Architecture and implementation for an institutional P2P lending marketplace for one of Europe's largest lenders ($9B portfolio).
Mbill - P2P Transfers
P2P transfer service for individuals and small-to-medium online merchants. Create a page for your card and share a link to receive payments. Includes customer cabinet, payment button constructor, and transaction reports.
Mastercard MoneySend
Front-end application to receive P2P transfers sent via recipient phone number. Country-wide rollout of phone-number-based transfers.
Forza - PayDay Loan Websites
Front-end, SMS gateway, decision engine, and marketing tools for an online lending originator operating in Moldova, Bosnia, and North Macedonia.
Best Wallet (ex. MBank)
eWallet cloud for worldwide money transfers. For B2C: pay for 2,700+ services across CIS, send money to phone numbers, cash out via partnered banks or cards. For B2B: free SaaS white-label eWallets for banks with simple integration.
IPSP.com - Payment Pages
Responsive landing and payment pages for an Internet Payment Service Provider. Improved conversion on payment flows via lighter UI.
ECommPay - Mobile App
iOS and Android business application for partners to manage payment platform on the go.
Autopayment
Automatically pays for bills based on two types of rules: by threshold of supplier balance (e.g., mobile top-up) or on a periodic basis.
Mobile Cashier
Turns Android devices into payment terminals for deposits and top-ups across numerous service providers, from cellular carriers to credit card loan repayments.
OnlyTTY
Share a shell or a single command through a link and control it from a browser or phone. Terminal traffic is end-to-end encrypted, and the relay never sees the session keys.
Sage - Sagas Pattern in Elixir
Dependency-free implementation of the Sagas pattern for distributed transactions with explicit compensation. Guarantees that either all transactions complete successfully, or compensating transactions amend partial execution.
LoggerJSON
Structured JSON logging for Elixir with first-class formatters for Google Cloud Logging, Datadog, and Elastic (ECS). Drop-in :logger formatter/handler with runtime config helpers.
Confex
Runtime configuration from environment variables with type casting and adapters (:system, :system_file). 12-factor friendly configuration for Elixir applications.
Elixir Bench
Continuous benchmarking platform for the Elixir ecosystem. Automatically runs performance benchmarks on each commit to detect regressions and track language performance improvements over time. Won Spawnfest 2017 and later accepted into Google Summer of Code.
Annon API Gateway
Configurable API gateway acting as a reverse proxy with a plugin system (ACL, Auth, Validation, CORS, Idempotency), request/response storage, metrics, management UI, and auth provider. Reduces boilerplate across services.
Ecto Mnesia Adapter
Ecto adapter for OTP's built-in Mnesia database that works in the same memory space as the application, providing extremely low latency without deploying a separate database.
Gandalf - Decision Engine
Open-source decision engine SaaS for rule tables, champion/challenger split testing, revision history, decision analytics, and debugging tools.
Man - Template Rendering Engine
Stores iex, mustache, or markdown templates and renders them with localization to HTML or PDF via REST JSON API. Includes an easy-to-use management UI. Free one-click deployment to Heroku.
Vagrant Box OS X
macOS Vagrant boxes for VirtualBox. Run UX tests or build iOS/Mac applications on any machine with a few CLI commands. Used by many teams worldwide, including Boxen. Got a $50k S3 bill in month one, was sponsored by Cloudflare for a while, and eventually taken down over Apple licensing.
Parasport - Foundation Portal
Medium-sized web portal for a foundation supporting Paralympic sport, physical rehabilitation, and social adaptation. Built on October CMS.
OneDayOfMine
Storytelling social network that helps see other people's lives through their eyes. Capture moments through the day and share them with descriptions - from special forces in Belarus to a family visit to a film museum in South Korea.
L15 - Night Club x Coworking
Experimental mix of coworking space and a night club ('clubworking') in Kyiv. Turned the office into a best-in-class night club and ran terrace events with world-class DJs every weekend for an entire summer.
Happy Customer
Outsource project to motivate small and medium-sized businesses to provide better customer service via public feedback and simple tracking.
truBrain 1.0
An early-stage product that needed help. I took some swings at UX and performance for free because I wanted to see them make it.
Blog
Your data warehouse is the wrong place to serve a dashboard
Customer-facing dashboards ask the same few questions all day, on data that's fine a few minutes stale - but every page load runs a live query against a warehouse that bills per query and was never built to sit behind a live screen. Here's the serving layer I built to move those reads onto cheap snapshots on my own infra.
Treating physical servers like cloud VMs
Modern BMCs turned bare metal into something you can terraform apply: declare a node in git, reimage it over the network, verify it against a receipt. How our cloud-to-on-prem migration kept the cloud workflow - and why that's exactly what LLM agents needed.
Your AI is brilliant. And blind
AI agents got good at writing code - and they're still flying blind on your infrastructure, guessing at problems they can't see. The obvious fix is to hand them SSH and let them run wild. Here's why I didn't, and what I built instead.
One brain, two agents: an OS for autonomous coding agents
AI agents lose context, stop early, and skip work. The fix is not a smarter prompt. It is a small, file-based operating system: a queue they cannot abandon, hooks they cannot ignore, and one shared source of truth.
Running an AI coding agent you can't trust
You can't trust an AI coding agent, and you shouldn't have to. Put it in a sandbox where the worst case is boring: one repo damaged, no secrets exposed, and a VM you can rebuild in a minute.
Design APIs with CDN in mind
Most APIs are designed for developer convenience, not cacheability. A few structural changes can make CDN do the heavy lifting for you.
The Real 10x Engineer
The real multiplier in software isn’t writing more code. It’s judgment: choosing the right problems, avoiding unnecessary systems, and reducing the maintenance burden that slows teams down.
Introducing Sage - a Sagas pattern implementation in Elixir
Distributed transactions are hard and expensive, if you wonder how to pragmatically handle them in a mid-size project - this article is for you.
Run stale tests on file change in Elixir
Mix is an awesome tool but most Elixir beginners are not aware of all its features. mix test --stale is one of them and can make your workflow much better.
Runtime configuration, migrations and deployment for Elixir applications
Shortly after moving from PHP to Elixir I've faced a common issue, the way we deploy applications is totally different from the one I'm used to.
National Health Service, on Elixir and Kubernetes
A look at building Ukraine’s national-scale eHealth platform with Elixir, Kubernetes, and pragmatic architecture for reliability and scale.
Bringing blockchain properties to centralized government databases
Making it cryptographically impossible to alter records in a database even with full system access.
Alternative approach for sensitive file uploads
Using signed URLs for secure file uploads directly to cloud storage, bypassing your application servers entirely.
Designing a P2P Lending platform with Elixir in mind
With this post, I want to share with you the design process on one of our latest projects - a P2P marketplace that was intended to be used by hundreds of thousands of users.