<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Sim-Pesa Is Live: A 16-Week Build Log, A Finished Product, and Everything In Between]]></title><description><![CDATA[Sim-Pesa Is Live: A 16-Week Build Log, A Finished Product, and Everything In Between]]></description><link>https://week-16.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Thu, 05 Nov 2026 02:24:02 GMT</lastBuildDate><atom:link href="https://week-16.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Sim-Pesa Is Live: A 16-Week Build Log, A Finished Product, and Everything In Between]]></title><description><![CDATA[Sim-Pesa Build Log — Week 16 of 16 Sim-Pesa is live. Sixteen weeks ago, I could not log into the M-Pesa developer portal. Today, I shipped a local-first…]]></description><link>https://week-16.hashnode.dev/sim-pesa-is-live-a-16-week-build-log-a-finished-product-and-everything-in-between</link><guid isPermaLink="true">https://week-16.hashnode.dev/sim-pesa-is-live-a-16-week-build-log-a-finished-product-and-everything-in-between</guid><dc:creator><![CDATA[Paul Murithi Kirera]]></dc:creator><pubDate>Tue, 12 May 2026 13:13:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/68f319caa305480f4cebccb8/ad91a303-d4fa-4dfb-8f85-612942018145.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Sim-Pesa Build Log — Week 16 of 16</em></p>
<hr />
<p>Sim-Pesa is live.</p>
<p>Sixteen weeks ago, I could not log into the M-Pesa developer portal. Today, I shipped a local-first transactional appliance that simulates the entire M-Pesa STK Push flow — queue, locking, retries, webhooks, and all.</p>
<p>If you are new here: Sim-Pesa is a containerised payment simulator I have been building in public, one week at a time, to level up as a software engineer. This is the final entry. Be sure to check out the <a href="https://hashnode.com/@paul-murithi">previous weekly blogs</a> if you want to follow the full journey.</p>
<p>Let's close it out properly.</p>
<hr />
<h2>1. Where It Started</h2>
<p>Four months ago, I wanted to understand how M-Pesa integrations actually work. The ecosystem that powers payments across East Africa felt like something I should know, but every time I tried to get started, I hit a wall.</p>
<p>The first attempt: YouTube tutorials. I could not follow them.</p>
<p>The second attempt: the official Daraja documentation. That day, the M-Pesa developer portal was refusing logins entirely — I never got in.</p>
<p>I eventually found Rizwan Hamisi's unofficial Daraja docs at <a href="https://mpesa-docs.vercel.app/">mpesa-docs.vercel.app</a>, which are genuinely excellent. But even then, I barely made it past the first page. The technical vocabulary alone was a problem — <em>callback URLs, webhooks, idempotency, asynchronous communication</em> — all of it was foreign to me.</p>
<p>My background at that point was Flask, Spring Boot, and university CRUD apps. Fintech was a different world.</p>
<p>I closed the docs and gave up.</p>
<hr />
<h2>2. The Idea</h2>
<p>A few weeks later, the itch came back.</p>
<p>M-Pesa integrations were clearly valuable to know. But I kept running into the same barrier: the tooling around Daraja is built for developers who already understand the domain. If you are new, the learning curve is steep and the feedback loops are slow — because everything depends on external services that you do not control.</p>
<p>That became my pain point. And a pain point is the beginning of a project.</p>
<p><em>What if I built a simulator that makes Daraja approachable? Something that runs entirely on localhost, with no external dependencies, and lets developers test payment flows without fighting the sandbox?</em></p>
<p>I scoped it tightly. One feature: M-Pesa Express, known as STK Push. The most used Daraja endpoint. Nothing else.</p>
<p>Then I wrote a 14-page technical spec and a 16-week timeline.</p>
<p>Looking at it at my skill level then, it felt like a document written for a startup team of experienced engineers. Not a solo student project. But I committed to it anyway.</p>
<hr />
<h2>3. The Build</h2>
<p>The first few weeks were rough.</p>
<p>I had never used Docker at scale, never touched Redis or BullMQ, and had only a surface-level understanding of PostgreSQL beyond basic queries. I was building with Node and TypeScript for the first time.</p>
<p>I fell into tutorial hell more than once. I started watching four-hour TypeScript courses and working through Docker documentation that ran to two hundred pages. At some point I realised that was the trap. You do not need to know everything about a tool before you can use it — you need to know just enough for what you are building right now.</p>
<p>Once I accepted that, things started moving.</p>
<p>Each week stacked knowledge onto the last. Concepts that had felt opaque started forming mental models. The technologies stopped feeling alien.</p>
<p>Some of the harder weeks:</p>
<ul>
<li><p><strong>Week 6</strong> — Concurrency control. I had to solve the problem of holding a database lock across human interaction time while a user enters a PIN. The answer was two-phase locking: acquire the lock, move the transaction to <code>PROCESSING</code>, release the database lock, then wait for the PIN event via Redis Pub/Sub. Simple in retrospect. Weeks of thinking to get there.</p>
</li>
<li><p><strong>Week 8</strong> — First time writing tests. Testing exposed every architectural shortcut I had taken. Coverage ended up at 66% overall, but 87.5% on the integrity core. Lesson: bad tests are a symptom of bad architecture, not the cause.</p>
</li>
<li><p><strong>Week 13</strong> — "UI week" turned into backend architecture week. Building real-time dashboard updates with Server-Sent Events forced a proper Redis Pub/Sub pipeline I had not planned for.</p>
</li>
</ul>
<p>Every week had a version of that. A plan, a wall, a rethink, a solution.</p>
<p>You can read the full weekly breakdown in the <a href="https://hashnode.com/@paul-murithi">build log series</a>.</p>
<hr />
<h2>4. What Sim-Pesa Is Now</h2>
<p>I started this project thinking of it as a learning exercise. Around Week 10 or 11, I stopped thinking of it that way.</p>
<p>It had become an actual tool.</p>
<p><strong>Sim-Pesa is a local-first M-Pesa API simulator.</strong> You run it with Docker, complete a short onboarding flow that takes under sixty seconds, and immediately have a fully functional payment environment on your machine — with no dependency on Safaricom's sandbox.</p>
<p>Here is what you get out of the box:</p>
<ul>
<li><p>STK Push simulation</p>
</li>
<li><p>Realistic webhook callbacks with the exact Daraja payload structure</p>
</li>
<li><p>Real-time transaction monitoring via a live dashboard</p>
</li>
<li><p>Manual PIN approval through a Virtual Smartphone UI</p>
</li>
<li><p>Automatic exponential backoff retry logic for failed webhooks</p>
</li>
<li><p>Intentional failure simulation (wrong PIN, insufficient funds, duplicate requests, cancelled transactions)</p>
</li>
<li><p>Persistent transaction history across restarts</p>
</li>
</ul>
<p>From your application's perspective, it behaves like a real M-Pesa environment.</p>
<h3>Who it is for</h3>
<p><strong>Hackathon teams.</strong> Integrating Daraja under time pressure is painful — credentials, callback URL tunnelling, sandbox instability, and networking issues can burn hours that belong to the product. Sim-Pesa lets a team spin up the full stack locally, point their application at it, and demo a working payment flow reliably. No external dependency. No tunnel configuration.</p>
<p><strong>Developers learning how payment systems work.</strong> Most tutorials show payments as synchronous: <em>send request → receive success</em>. Real systems are not like that. Payments are asynchronous. They involve queues, state transitions, retries, concurrency issues, webhook delivery, and human interaction delays. Sim-Pesa exposes those moving parts instead of hiding them.</p>
<p>You can watch a transaction move through <code>PENDING → PROCESSING → SUCCESS</code> or branch into <code>FAILED</code> and <code>CANCELLED</code>. You can simulate wrong PINs, duplicate submissions, and delayed callbacks. The goal is not to fake payments — it is to help developers understand how transactional systems actually behave.</p>
<p><strong>Developers building payment integrations locally.</strong> Development environments that depend on external services you do not control are fragile. The sandbox is sometimes down. Callbacks sometimes never arrive. Requests timeout for no clear reason. Sim-Pesa moves the entire environment onto localhost — database, queue, worker, API, and dashboard — inside a self-contained Docker appliance. The environment becomes deterministic. That changes the developer experience more than I expected.</p>
<p><strong>Anyone who wants to understand distributed systems visually.</strong> The Virtual Smartphone, live transaction feed, and real-time state updates turn invisible backend concepts into something interactive. Instead of just reading about asynchronous processing, eventual consistency, and transactional integrity, you can watch them happen. If you want to go deeper, you can subscribe directly to the Redis channels and watch the signals flowing through the system in real time.</p>
<hr />
<h2>5. What's Next</h2>
<p>This project is finished. I do not think it is complete.</p>
<p>Sim-Pesa achieved what I set out to build. I wanted to deeply understand transactional systems, asynchronous workflows, queue-based architecture, concurrency control, and how real payment infrastructure behaves under pressure. Building it forced me to confront every one of those concepts directly, in a working system, with real consequences for getting it wrong.</p>
<p>But there is still a lot that can be improved:</p>
<ul>
<li><p>More realistic failure simulations</p>
</li>
<li><p>Additional Daraja API endpoints beyond STK Push</p>
</li>
<li><p>Webhook replay tooling</p>
</li>
<li><p>Metrics dashboards and stronger observability</p>
</li>
<li><p>CLI tooling for faster developer setup</p>
</li>
<li><p>Multi-merchant support</p>
</li>
<li><p>Better frontend polish</p>
</li>
<li><p>Deeper contributor documentation</p>
</li>
</ul>
<p>The idea itself has room to grow too. As M-Pesa integrations become more common across East Africa, developers need better local development tooling. Building payment integrations should not require fighting an unstable sandbox before you can even test your own business logic. That is the problem Sim-Pesa is trying to address.</p>
<p>If you are a developer who wants to dig in:</p>
<ul>
<li><p><strong>Docs:</strong> <a href="https://simpesa-docs.vercel.app/">simpesa-docs.vercel.app</a></p>
</li>
<li><p><strong>GitHub:</strong> <a href="https://github.com/paul-murithi/simpesa">github.com/paul-murithi/simpesa</a></p>
</li>
</ul>
<p>Clone it. Break things. Raise issues. Open pull requests. Suggest ideas.</p>
<p>Somewhere around Week 6, this stopped being purely about me learning backend engineering. It became an experiment in building better developer experience around payment systems. I would like to see where that goes with more people involved.</p>
<hr />
<p><em>This is the final entry of the Sim-Pesa build log. Sixteen weeks, sixteen posts, one finished product. Thanks for following along.</em></p>
<hr />
<p><strong>Tags:</strong> <code>#mpesa</code> <code>#daraja</code> <code>#docker</code> <code>#nodejs</code> <code>#typescript</code> <code>#postgresql</code> <code>#redis</code> <code>#bullmq</code> <code>#fintech</code> <code>#buildinpublic</code> <code>#devtools</code> <code>#eastafrica</code> <code>#100daysofcode</code> <code>#backend</code></p>
]]></content:encoded></item></channel></rss>