Blog

Writing about software engineering, architecture decisions, and lessons learned

August 4, 2026

Production RAG: Three Retrieval Strategies and When Each One Wins

The RAG demo takes a weekend. Then retrieval silently misses, the model answers anyway — fluently wrong — and nobody files a bug because the answer reads right. Three retrieval strategies, from single-shot vector search to agentic loops, and the trade-offs that decide which one you need.

ragllmarchitecture
August 3, 2026

Running an AI Software Factory: Agents That Ship Production Code

How we restructured development at Navero so AI agents implement, verify, and review tickets end to end — with humans holding only the gates that matter.

ai-agentsautomationdeveloper-productivity
August 3, 2026

Prompt Engineering Without Guesswork: Evals, Naive Prompts, and Reliable JSON

Most teams write prompts by vibes: tweak, run once, ship, break in production. Here is the scientific loop instead, with real eval scores, the mistakes everyone makes, which model tier fits which job, and the prefill plus stop sequence trick for JSON that always parses.

llmprompt-engineeringevals
July 28, 2026

Local-First and CRDTs: From Naive Sockets to a Scalable Collaborative Editor

Why broadcasting keystrokes over Socket.IO falls apart, how OT and CRDTs keep documents converging, what local-first buys your UX, and how we built Cynoia's collaborative editor with Yjs, Lexical, IndexedDB persistence, and Socket.IO scaled through the Redis adapter.

crdtlocal-firstyjsreal-time
July 21, 2026

End-to-End Testing LLM Features Without Calling an LLM

How we run full-stack Playwright suites over AI generation flows with zero API keys, zero cost, and zero flakiness — by swapping every model for a deterministic in-process fake.

testingllmplaywright
July 7, 2026

Taming LLM Variance: Ensemble Scoring with Outlier Rejection

The same CV got a different score on every run. We fixed it with parallel ensemble scoring, statistical outlier rejection, and an eval that told us exactly how many attempts to pay for.

llmevalspython
June 18, 2026

Never Lose an Interview: Resilient Video Uploads from the Browser

Candidates record proctored video interviews on flaky laptops and flakier Wi-Fi. Here is the IndexedDB + Web Worker + resumable-upload pipeline that stopped us from losing recordings.

frontendreliabilityweb-workers
June 2, 2026

Building a Proctored Test Runner as an Explicit State Machine

Camera checks, fullscreen enforcement, anti-cheat, and screen recording — coordinated by a typed lifecycle state machine instead of a tangle of React effects.

reactstate-machinestypescript
December 15, 2025

Event-Driven Video Processing on GCP: Killing the Request That Could Never Finish

Transcription takes 2–5 minutes; load balancers give up long before that. Why the synchronous version of Navero's video screening pipeline was structurally doomed, and how GCS events, Cloud Functions, and async webhooks replaced it — with the costs stated honestly.

architecturegcpevent-driven
August 20, 2025

Why Your Cron Jobs Run Three Times: Zookeeper Leader Election for Horizontally Scaled Node.js

The moment you run a second instance, every scheduled job runs twice — and a scheduled broadcast reaches real users twice. How we solved it in Hexabot (open-source chatbot, 700+ stars) with Zookeeper leader election, after the naive fixes failed.

open-sourcechatbotdistributed-systems
May 10, 2025

Real-Time Collaboration: The Editing Is the Easy Part

CRDTs solve concurrent editing — a library import solves it for you. What nobody warns you about is everything around it: permissions enforced at the socket, presence, offline recovery, and network partitions. Field notes from building Cynoia's collaborative editor.

crdtwebsocketsreal-time