<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Davide Angelocola</title>
  <link href="https://dfa1.github.io/feed.xml" rel="self" type="application/atom+xml"/>
  <link href="https://dfa1.github.io/"/>
  <updated>2026-08-08T00:00:00Z</updated>
  <author>
    <name>Davide Angelocola</name>
  </author>
  <id>https://dfa1.github.io/feed.xml</id>

  <entry>
    <title>RocksDB Performance and Zero-Copy</title>
    <link href="https://dfa1.github.io/articles/rocksdb-performance-and-zero-copy.html"/>
    <id>https://dfa1.github.io/articles/rocksdb-performance-and-zero-copy.html</id>
    <updated>2026-08-08T00:00:00Z</updated>
    <published>2026-08-08T00:00:00Z</published>
    <author>
      <name>Davide Angelocola</name>
    </author>
    <summary>rocksdbffm, the FFM-based RocksDB binding I wrote about last time. Here's what it took to get reads down to zero allocations — and what the benchmarks had to say about it.</summary>
  </entry>
  <entry>
    <title>Build the Loop, Not the Prompt</title>
    <link href="https://dfa1.github.io/articles/build-the-loop-not-the-prompt.html"/>
    <id>https://dfa1.github.io/articles/build-the-loop-not-the-prompt.html</id>
    <updated>2026-07-06T00:00:00Z</updated>
    <published>2026-07-06T00:00:00Z</published>
    <author>
      <name>Davide Angelocola</name>
    </author>
    <summary>Recently I built three small Java libraries using JDK 25 and the Foreign Function &amp; Memory API: rocksdbffm, vortex-java, and zstd-java. Most of the code was written by an AI agent. The lesson that stuck wasn't about the model: an agent is only as good as the harness around it — a safe language to write in, and a tight loop of tools to catch it when it's wrong.</summary>
  </entry>
  <entry>
    <title>Earn Your Rules</title>
    <link href="https://dfa1.github.io/articles/earn-your-rules.html"/>
    <id>https://dfa1.github.io/articles/earn-your-rules.html</id>
    <updated>2026-07-04T00:00:00Z</updated>
    <published>2026-07-04T00:00:00Z</published>
    <author>
      <name>Davide Angelocola</name>
    </author>
    <summary>Once in a while, someone shares an "X rules of software engineering" list and I find myself agreeing with about a third of it. This is my pass through one such list — keeping what I've actually had to write down somewhere, dropping what I haven't, and rewriting the rest in my own language. Each rule opens with an extract from the story where it was earned.</summary>
  </entry>
  <entry>
    <title>Decouple Allocations from Request Volume</title>
    <link href="https://dfa1.github.io/articles/decouple-allocations-from-request-volume.html"/>
    <id>https://dfa1.github.io/articles/decouple-allocations-from-request-volume.html</id>
    <updated>2023-11-30T00:00:00Z</updated>
    <published>2023-11-30T00:00:00Z</published>
    <author>
      <name>Davide Angelocola</name>
    </author>
    <summary>Millions of requests per day. RocksDB as the storage engine, returning variable-size values. Nothing about this load profile suggests a performance problem. The implementation has a structural flaw: allocation rate scales with request rate, when it should scale with concurrency.</summary>
  </entry>
  <entry>
    <title>Rethink Domain Primitives with Valhalla</title>
    <link href="https://dfa1.github.io/articles/rethink-domain-primitives-with-valhalla.html"/>
    <id>https://dfa1.github.io/articles/rethink-domain-primitives-with-valhalla.html</id>
    <updated>2026-05-16T00:00:00Z</updated>
    <published>2026-05-16T00:00:00Z</published>
    <author>
      <name>Davide Angelocola</name>
    </author>
    <summary>Your Compiler Is Already Part of Your Security Team made the case for domain primitives: encode constraints in types, the compiler enforces them forever. The recurring objection — a wrapper class per int is one heap object per value, plus a pointer to reach it. Fine at the boundary; questionable in a hot loop where allocations and cache misses dominate.</summary>
  </entry>
  <entry>
    <title>The Cost of Implicitness</title>
    <link href="https://dfa1.github.io/articles/the-cost-of-implicitness.html"/>
    <id>https://dfa1.github.io/articles/the-cost-of-implicitness.html</id>
    <updated>2026-05-09T00:00:00Z</updated>
    <published>2026-05-09T00:00:00Z</published>
    <author>
      <name>Davide Angelocola</name>
    </author>
    <summary>You don't pay for implicit assumptions when you write them. You pay when a new joiner interprets them differently, when two teams deploy on different schedules and discover the shared understanding was never shared, when a hotfix swaps two int arguments that meant two different things and the compiler had no opinion. The cost is deferred, invisible, and always larger than expected.</summary>
  </entry>
  <entry>
    <title>The Slow Fix</title>
    <link href="https://dfa1.github.io/articles/the-slow-fix.html"/>
    <id>https://dfa1.github.io/articles/the-slow-fix.html</id>
    <updated>2026-04-30T00:00:00Z</updated>
    <published>2026-04-30T00:00:00Z</published>
    <author>
      <name>Davide Angelocola</name>
    </author>
    <summary>This is a success story from when I was working as a consultant in the mid 2010s. This is an extract from notes I took at that time. The inspiration is "The Phoenix Project" — minus the novel format. The goal here is simpler: document what happened, in case it's useful to someone standing at the same starting point.</summary>
  </entry>
  <entry>
    <title>Make the Implicit Explicit</title>
    <link href="https://dfa1.github.io/articles/make-the-implicit-explicit.html"/>
    <id>https://dfa1.github.io/articles/make-the-implicit-explicit.html</id>
    <updated>2026-04-23T00:00:00Z</updated>
    <published>2022-06-10T00:00:00Z</published>
    <author>
      <name>Davide Angelocola</name>
    </author>
    <summary>A Data API with per-request authorization — entitlements delegated to an Entitlement API owned by a separate team. A series of forced decisions — versioned contracts, point-in-time consistency, decorator-based composition — each driven by a different problem. This is a retrospective on a real system.</summary>
  </entry>
  <entry>
    <title>From BPF to eBPF, Twenty Years Later</title>
    <link href="https://dfa1.github.io/articles/from-bpf-to-ebpf-twenty-years-later.html"/>
    <id>https://dfa1.github.io/articles/from-bpf-to-ebpf-twenty-years-later.html</id>
    <updated>2026-04-19T00:00:00Z</updated>
    <published>2026-04-19T00:00:00Z</published>
    <author>
      <name>Davide Angelocola</name>
    </author>
    <summary>In 2004, I wrote a packet sniffer called pangolin. It filtered network traffic using BPF — Berkeley Packet Filter. Raw bytecode. No compiler, no abstraction. Instructions for a virtual machine running inside the Linux kernel, written by hand. Twenty years later, I compiled pangolin on kernel 6.17 on ARM64. One type fix — size_t → socklen_t — and it ran. The bytecode in filters.c was untouched. That got me curious. The bytecode survived twenty years unchanged — what did the tooling around it become? Brendan Gregg's eBPF overview was the map I used to find out.</summary>
  </entry>
  <entry>
    <title>Java + RocksDB - JNI</title>
    <link href="https://dfa1.github.io/articles/java-plus-rocksdb-minus-jni.html"/>
    <id>https://dfa1.github.io/articles/java-plus-rocksdb-minus-jni.html</id>
    <updated>2026-04-11T00:00:00Z</updated>
    <published>2026-04-11T00:00:00Z</published>
    <author>
      <name>Davide Angelocola</name>
    </author>
    <summary>The best way I know to learn something is to build something real with it. I wanted to understand Java's Foreign Function &amp; Memory (FFM) API properly — not just read the Javadoc, but actually use it. RocksDB was the obvious vehicle: I'm a long-time user of RocksDB and it has a well-defined C API and a problem space I already understood. The result is rocksdbffm: an experimental RocksDB wrapper for Java using FFM instead of JNI.</summary>
  </entry>
  <entry>
    <title>Coding with Claude Code: A Week on hosh</title>
    <link href="https://dfa1.github.io/articles/coding-with-claude-code.html"/>
    <id>https://dfa1.github.io/articles/coding-with-claude-code.html</id>
    <updated>2026-03-29T00:00:00Z</updated>
    <published>2026-03-29T00:00:00Z</published>
    <author>
      <name>Davide Angelocola</name>
    </author>
    <summary>I've been experimenting with Claude Code on my side project hosh, an experimental shell written in Java. After a few days of pairing with an AI agent on real tasks — adding features, fixing bugs, resolving SonarQube warnings — here's what I found.</summary>
  </entry>
  <entry>
    <title>Your Compiler is already part of your Security Team</title>
    <link href="https://dfa1.github.io/articles/your-compiler-is-already-part-of-your-security-team.html"/>
    <id>https://dfa1.github.io/articles/your-compiler-is-already-part-of-your-security-team.html</id>
    <updated>2026-04-17T00:00:00Z</updated>
    <published>2021-01-04T00:00:00Z</published>
    <author>
      <name>Davide Angelocola</name>
    </author>
    <summary>It's 3am. Your phone is ringing. A few hours earlier you deployed a hotfix — straightforward change, reviewed in a hurry, went out clean. Now some important data is being published under the wrong market. Instruments from exchange A showing up under exchange B. Clients are seeing it. Someone is already asking if it's a breach. It isn't. It's worse, in a way: the hotfix swapped two arguments. The method took a marketId and an instrumentId, both ints, and the caller got them the wrong way round. The compiler saw two ints, both positive, both in range. Code compiled, tests passed, CI was green.</summary>
  </entry>
  <entry>
    <title>Write Down the Why</title>
    <link href="https://dfa1.github.io/articles/write-down-the-why.html"/>
    <id>https://dfa1.github.io/articles/write-down-the-why.html</id>
    <updated>2020-10-01T00:00:00Z</updated>
    <published>2020-10-01T00:00:00Z</published>
    <author>
      <name>Davide Angelocola</name>
    </author>
    <summary>Late 2019, early 2020. A newly formed team, building the next generation of a financial reference data platform from scratch. Several developers who never worked together, a greenfield project, a deadline, and two problems we had not yet named: a testing approach that would take us a while to outgrow, and a branching model we had not agreed on yet. Every team has a moment where brute force stops working. Ours came on two fronts at once. Without a shared "why" every engineer filled in the gaps differently.</summary>
  </entry>
  <entry>
    <title>The Joy of Proper Encapsulation</title>
    <link href="https://dfa1.github.io/articles/the-joy-of-proper-encapsulation.html"/>
    <id>https://dfa1.github.io/articles/the-joy-of-proper-encapsulation.html</id>
    <updated>2026-03-27T00:00:00Z</updated>
    <published>2026-03-27T00:00:00Z</published>
    <author>
      <name>Davide Angelocola</name>
    </author>
    <summary>Today I pushed a commit to hosh. The commit message was innocent enough: fix: avoid usage of jdk.internal.Signal. The diff was 20 lines added, 31 removed. And it was wrong — not syntactically, but semantically. It changed the behavior of my program in a way I didn't fully appreciate until I sat down and thought about what the Java Platform Module System was actually telling me. This is a story about that mistake, and about why I think Java's module system, for all the grief it gets, is one of the best things that happened to the platform.</summary>
  </entry>

</feed>
