Filipe Estacio
Software engineer. Notes on things I build, break, and learn along the way.
Recent posts
When ESM Meets CJS: How Silent Bundling Failures Broke 98 Lambdas
We migrated Lambda deployments from CDK to OpenTofu. Everything looked green. Days later, 98 out of 160 handlers were silently broken — and three invisible failures conspired to hide it.
The Invisible Bug That Broke 98 Backend Services — And Hid For Eight Days
A routine library update silently broke most of our backend services. Three separate systems conspired to hide the damage for over a week. Here's what happened and how we made sure it can't happen again.
What Production Taught Us About Self-Hosted Runners
We built self-hosted GitHub Actions runners on AWS. Then production taught us about shallow spot pools, ephemeral runner blind spots, and why your fleet strategy matters more than your architecture.
What Production Taught Us About Self-Hosted Runners
We built our own CI servers on AWS. Then production taught us about running out of server capacity, hidden timing bugs, and why your fleet strategy matters more than your architecture.
Every AI Coding Tool: A Solo Developer's 14-Month Odyssey (Part 1)
One developer, 3,667 commits, and a trail of abandoned AI tool configurations. Part 1 covers the pre-Claude Code era: Cursor, Kiro, Warp AI, OpenSpec, OpenCode, and the BMAD Method.
Every AI Coding Tool I Tried (And Why I Kept Ditching Them): Part 1
One developer, 14 months, and a revolving door of AI coding assistants. The story of treating AI tools like dating apps -- always convinced the next one would be The One.
Every AI Coding Tool: A Solo Developer's 14-Month Odyssey (Part 2)
After churning through Copilot, Cursor, Aider, Cline, Roo Code, and Windsurf, I stopped switching tools and started building a system. Claude Code, subagent-driven development, and a 480-line AGENTS.md that finally made AI collaboration work.
Every AI Coding Tool I Tried (And Why I Kept Ditching Them): Part 2
After months of chasing the perfect AI tool, I stopped switching and started building a system. Here's what finally made AI collaboration actually work.
Kraftwork: Building a Workflow Engine for AI-Assisted Development
Claude Code changed how I build software. But unstructured AI coding doesn't scale. So I built Kraftwork: a modular workflow system with spec-driven planning, worktree isolation, vendor-agnostic provider interfaces, and local persistent intelligence.
Kraftwork: Building a Proper Workflow for AI-Assisted Development
AI coding tools are brilliant at the small stuff. Coordinating work across multiple tickets, keeping plans alive during implementation, and remembering what you learned last week -- that's still on you. So I built a system to handle it.
3,704 Commits Later: From create-next-app to Production as a Solo Dev
14 months, one developer, 5 portals, 8 AWS accounts, and more false starts than I'd like to admit. A retrospective on building a production SaaS from scratch with AI tools.
3,704 Commits Later: What a Year of Solo SaaS Development Actually Looks Like
14 months, one developer, 5 web portals, and more wrong turns than right ones. An honest retrospective on going from a blank project to a live production system.
From Click-and-Pray to Merge-and-Forget: Our Road to Continuous Delivery
How a small startup went from manual production deploys and an accidentally misconfigured account to a fully automated pipeline where merging to main reaches production in minutes.
How We Got From 'Someone Remember to Deploy This' to 'Just Merge the PR'
We audited our deployment setup and found a bug that had hidden for months. Here's how we built a pipeline that goes from code merge to production in 15 minutes with no human in the loop.
How We Fixed Turbo Remote Cache 502s by Bypassing a Turborepo Client Bug
Our CI pipeline was losing 13 minutes per merge because large cache artifacts silently failed to upload. The fix required working around a bug in Turborepo's own HTTP client.
How We Fixed Our Broken Build Cache (By Working Around a Bug We Found in the Tool)
Our CI pipeline was silently wasting 13 minutes on every deployment because of a size limit nobody told us about. Then we found a bug in the caching tool itself.
Build Once, Deploy Everywhere: Replacing Vite's Build-Time Env Vars with Runtime Config
Our Vite SPAs rebuilt identical code for every environment because env vars were baked in at build time. We replaced them with a runtime config.json pattern that cut production deploys from 12 minutes to under 2.
Build Once, Deploy Everywhere: How We Cut Production Deploys from 12 Minutes to 90 Seconds
Our frontend apps rebuilt from scratch for every environment because configuration was baked in at build time. We fixed that with a pattern that made production deploys almost instant.
Building Self-Hosted GitHub Actions Runners on AWS: From Webhook to Custom AMI
The full arc of replacing GitHub-hosted runners with ephemeral EC2 instances: webhook-driven orchestration, spot instance fallback chains, an ARM64 detour, and a custom AMI pipeline that cut boot time by 80%.
We Built Our Own CI Machines on AWS (And It Was Worth It)
GitHub's hosted build servers were costing us too much and taking too long. Here's how we replaced them with our own setup on AWS, including the ARM64 detour that cost us two weeks.
The CloudFormation Export Lock: How CDK's Simplest Feature Creates Your Hardest Outage
Your CDK stacks pass certificates and hosted zones between each other with a single line of code. Under the hood, each line creates an invisible lock that will block you at the worst possible moment.
The Hidden Lock That Blocks Infrastructure Changes at the Worst Moment
A 3am certificate outage led us to discover that our cloud infrastructure had invisible locks stopping us from making changes. What looked like a routine fix turned into a maze of dependencies we didn't know existed.
Ditching Nx for Turborepo: A Migration Story in One Saturday
We replaced Nx with Turborepo in a 40-package TypeScript monorepo. The migration took a single day, deleted 3,500 lines, and taught us more about our own build system than we expected.
We Switched Build Tools, Deleted 3,000 Lines, and It Took One Saturday
We replaced the tool that orchestrates our 40-package codebase with a simpler one. The surprising part: we'd already done this migration before, in reverse.
When Your Read Endpoints Secretly Write: Refactoring Audit Logging with EventBridge
A routine IAM tightening broke staging because two read endpoints were secretly writing audit records to DynamoDB. The fix led us to event-driven audit logging, a clean separation of gates and side effects, and the discovery that half the infrastructure was already built.
When Tightening Security Breaks Your App: A Lesson in Hidden Side Effects
We tightened our security permissions, and two read-only features immediately broke. The reason revealed an architectural problem hiding in plain sight -- and the fix was cleaner than anything we'd planned.
From Stateless Chatbot to Persistent Agent: Building an Internal AI Chat That Actually Remembers
How we turned a forgetful chatbot into a persistent AI agent with sliding window context, rolling summaries, tool use, and shared conversations - all on DynamoDB.
Building an AI Chat That Actually Remembers What You Were Talking About
Our internal AI chatbot had no memory between questions. Here's how we built something that remembers conversations, shares them between team members, and knows when to look things up.
We Rewrote Our Rust Lambdas in TypeScript (And It Was the Right Call)
Everyone's rewriting things in Rust. We did the opposite - migrating 6 Rust Lambda functions (~5,500 LOC) to TypeScript. Here's why going against the trend was the most pragmatic engineering decision we made.
We Rewrote Rust Code in TypeScript, and I Have No Regrets
Everyone writes blog posts about how they moved to Rust. We went the other way, and it made everything simpler and faster to ship.
I Declared My Entire Dev Environment in 150 Lines of Nix
After 12 months of accumulating tool configs across multiple AI coding tools, I nuked it all and replaced it with a Nix flake. Node.js, pnpm, AWS CLI, CDK, secrets, terminal multiplexer - one command to rule them all.
I Replaced a Year of Accumulated Mess With One File
My development setup was a house of cards held together by hope and muscle memory. I spent two days replacing all of it with a single configuration file.
The Authentication Round-Trip: Cognito to WorkOS and Back Again
I left Cognito for WorkOS AuthKit because it was prettier. Two months later we came back, tail between our legs. Then we spent another month figuring out which Cognito auth flow to actually use.
We Left Our Auth Provider for a Prettier One. We Came Back.
In July we migrated away from AWS Cognito because it was ugly. In September we migrated back because the maths didn't work. Then we spent another month figuring out which bit of Cognito to actually use.
Herald: An AI Changelog System Built in a Day and Abandoned in a Week
I used AWS's AI coding agent to build an entire automated changelog system in a single day. Fifteen commits, full CDK infrastructure, Bedrock integration. It never saw production. Here's why that's a problem.
I Built an Entire Product in a Day and Deleted It Three Months Later
I used a new AI coding tool to build a complete automated changelog system from scratch. It had multiple components, proper infrastructure, monitoring, and tests. It had zero users. Here's what that says about AI-assisted development.