Posts

The hard part of an internal tool isn't the code

Leul Tadesse · August 8, 2026
Introduction
Internal tools
Data
I'm Leul, a software engineer in Addis Ababa. I spend most of my time building the unglamorous half of software — the survey platform your team fills in, the dashboard finance opens on Monday morning, the form that replaced a spreadsheet nobody trusted. I came to this from Electrical Engineering. I studied at Mekelle and then Hawassa, graduating in 2023, and somewhere in the middle of that I found I preferred systems I could change on a Tuesday afternoon to systems that needed a fabrication run. The instinct carried over more than I expected: measure the thing, find where the signal is getting lost, fix that. This is the first post here, so it should probably say what I think — not just what I've done. Every internal tool I've built has followed the same shape. The engineering estimate is roughly correct. The project still takes twice as long. And when I look back at where the time actually went, it is almost never in the code. It goes into answering questions like: which revenue number is the revenue number. Whether a deal that was signed in March but invoiced in April counts as March. Who is allowed to correct a record after the fact. These sound like process questions, and they get treated as someone else's problem, but they are schema questions wearing a disguise. You cannot build the dashboard until they are settled, and settling them is the job. On the profitability dashboard the thing that saved the most time was drawing canonical data boundaries early — deciding, before writing the ingestion, which system owned which fact. On Shega Insight it was naming Airtable as the source of truth and refusing to let the app become a second one. Neither is a technical achievement. Both are the reason those projects shipped. The second thing I keep relearning: a plain KPI that a stakeholder understands changes behaviour faster than a model that is more correct but needs explaining. I have built the sophisticated version. It gets admired in the review and then quietly ignored, because nobody wants to defend a number they can't derive themselves. The version that gets used is the one where someone can point at a figure and say "that's last quarter's margin, and I know where it came from." That's not an argument against rigour. It's an argument that legibility is a feature, and that it deserves the same care as the query underneath it. On the survey platform, the single best decision was keeping the data model simple. Every reporting question afterwards was easy, because the shape of the data hadn't been optimised for the first feature at the expense of the tenth. The corollary I've had to learn the hard way: realtime is a feature with a cost. It's excellent for a dashboard people watch. It also needs rate-limiting and batching the moment it meets real traffic, and that work is invisible until it isn't. Notes from this kind of work — data modelling, internal tooling, the parts of a Next.js and PostgreSQL stack that only show up under load. Things I got wrong and what the fix turned out to be. If you're building something similar and want to compare notes, my details are on the about page. I'd genuinely rather hear where you disagree.