
Fullstack Engineer specializing in AI security, self-healing automation, and production-grade multi-tenant systems.
About
React and Next.js on the front, Node.js and Python (FastAPI) on the back — I own the full stack and ship features that stay shipped.
LangGraph agents, RAG pipelines with hallucination detection, and human-in-the-loop validation so your AI system is as reliable in month six as it was on launch day.
Certified n8n Ambassador. I build multi-agent automation that runs 24/7 — not demo workflows, but production systems with retries, observability, and owned databases.
Multi-tenant design, per-tenant cache tagging, Row-Level Security, and CI/CD that makes deployments boring — in the best way.
Work Experience
See all →Senior Full-stack Developer · LohnPulse
2026 — Present · Remote
- Production SaaS managing complex payroll workflows and tax advisor data with strict RBAC and Row-Level Security.
- Implemented Next.js 15 Partial Pre-rendering: static shell served from the edge in <50ms with user-specific data streamed via React Server Components.
- Dynamic per-tenant cache tagging for granular CDN purges, JWT verification, and tenant context injection at the middleware edge layer.
- Maintained 194+ Playwright tests (E2E, API, UI) ensuring zero-regression production deployments.
Education

Studied at Ethiopia’s flagship university, with coursework spanning algorithms, software engineering, databases, and systems design through an information science lens. Built a strong foundation in problem-solving, research, and building reliable software, skills I still lean on when designing fullstack systems, AI workflows, and production automation today.
Achievements
Recognized as an official n8n Ambassador for contributions to workflow automation and production-grade n8n implementations.
Tech Stack
Languages & Frameworks
Data & Storage
AI & Automation
Architecture & DevOps
Projects
See all →Pest Leads Pro
Multi-agent automation platform powering a pest-control lead generation SaaS. Core design: an n8n Router Agent that scores inbound leads, routes them to matched vendors, and manages credits autonomously — no human dispatch required. A separate Digital PR agent monitors incident spikes, generates AI press pages, and fires Hunter.io outreach to earn backlinks at scale. Four background agents (Gardener SEO, Performance Manager, Auditor, Reporter) run on schedule and write results back to PostgreSQL. The frontend surfaces embed APIs, geo/FAQ widgets, and an A/B-configurable AI chat widget built on top of the same data layer.

Aegis Agent
Autonomous portfolio concierge backend: agentic RAG over Supabase pgvector, intent routing, confidence-gated answers, Google Calendar and Meet booking, and human-in-the-loop handoff for sensitive leads. FastAPI service with LangGraph-style orchestration, session memory, and lead logging. Powers the live chat agent on this portfolio.
Dual-Agent Architecture AI
Production-ready dual-agent system where a Planner agent decomposes user goals into structured subtasks and a Worker agent executes them with isolated context. Implements structured handoff protocols, error recovery, and observable step-by-step output so failures surface at the right layer. Deployed as an interactive Next.js demo; the patterns map directly to production LLM workflows.
Eset Coffee
Full marketing and e-commerce web presence for Eset Coffee, an Ethiopian specialty coffee brand. Covers product storytelling, origin traceability pages, and ordering touchpoints — built with Next.js and TypeScript for fast load times and strong SEO.
Hobbies
Away from shipping code: football, competitive practice on LeetCode & Codeforces, and reading that keeps me grounded.

The idea isn’t to care about nothing; it’s to care on purpose. I try to reserve my focus for work and relationships that actually deserve it, and to say a polite ‘not now’ to noise, vanity metrics, and drama. Same insight as the loud title, just how I’d explain it at the dinner table.
I follow and play football when I can; it's the reset button after long debugging sessions.
I once treated a Friday deploy as ‘just a small config tweak’ with no rollback story. The weekend re-taught me that ‘small’ and ‘safe’ are different words. Now Fridays respect blast radius.
Past me loved optimizing queries I hadn’t measured yet. These days I log first, prove the pain, then buy performance with real numbers—not vibes.
I used to skip tests when I was ‘in the zone’. The zone lied; prod didn’t. Tests are how I stay honest when confidence feels free.
I assumed stakeholders read the doc if I linked it once. They were busy; I was naive. A one-line summary beats a perfect PDF nobody opens.
I’ve nuked calm afternoons with a cheerful `git push --force` on shared branches. Branches are multiplayer; I treat shared history like glassware now.
I shipped ‘one more feature’ before fixing onboarding friction. Users don’t applaud features they never reach—clarity beats breadth on week one.
I learned that retries without backoff are just polite DDoS machines aimed at myself. Backoff, jitter, idempotency—boring words, quiet weekends.
I used to debate architecture in my head for days instead of sketching a box diagram for twenty minutes. Paper is cheaper than rewrite season.
I once waited too long to say ‘this timeline is fiction’. Silence felt kind; it wasn’t. Early honesty is respect, not pessimism.
I trusted env var names from memory across environments once. One typo taught me that ‘works on my machine’ should never be the only oracle.
I treated caching as free speed until stale data embarrassed me in front of users. Cache is a contract: who invalidates, when, and how loudly.
I merged without a rollback checklist because the release felt easy. Easy releases are exactly when the weird edge cases throw a party.
I’ve defended my code like it was my pet. Code isn’t identity; it’s inventory. Review comments are edits, not attacks.
I wrote long Slack threads instead of a 5‑minute call. Sometimes async is efficient; sometimes it’s procrastination in a trench coat.
I copied a regex from Stack Overflow without a test case. I won’t describe what broke; therapy helped. Regex gets tests now.
I ignored observability because the MVP ‘wasn’t ready for metrics yet’. Prod was ready for incidents; logs arrived one panic too late.
I said yes to scope creep because saying no felt rude. Boundaries aren’t rudeness—they’re how quality survives contact with reality.
I compared my chapter one to someone else’s chapter twelve. Useful for humility; useless for planning. Run your own race with your own constraints.
I once treated a Friday deploy as ‘just a small config tweak’ with no rollback story. The weekend re-taught me that ‘small’ and ‘safe’ are different words. Now Fridays respect blast radius.
Past me loved optimizing queries I hadn’t measured yet. These days I log first, prove the pain, then buy performance with real numbers—not vibes.
I used to skip tests when I was ‘in the zone’. The zone lied; prod didn’t. Tests are how I stay honest when confidence feels free.
I assumed stakeholders read the doc if I linked it once. They were busy; I was naive. A one-line summary beats a perfect PDF nobody opens.
I’ve nuked calm afternoons with a cheerful `git push --force` on shared branches. Branches are multiplayer; I treat shared history like glassware now.
I shipped ‘one more feature’ before fixing onboarding friction. Users don’t applaud features they never reach—clarity beats breadth on week one.
I learned that retries without backoff are just polite DDoS machines aimed at myself. Backoff, jitter, idempotency—boring words, quiet weekends.
I used to debate architecture in my head for days instead of sketching a box diagram for twenty minutes. Paper is cheaper than rewrite season.
I once waited too long to say ‘this timeline is fiction’. Silence felt kind; it wasn’t. Early honesty is respect, not pessimism.
I trusted env var names from memory across environments once. One typo taught me that ‘works on my machine’ should never be the only oracle.
I treated caching as free speed until stale data embarrassed me in front of users. Cache is a contract: who invalidates, when, and how loudly.
I merged without a rollback checklist because the release felt easy. Easy releases are exactly when the weird edge cases throw a party.
I’ve defended my code like it was my pet. Code isn’t identity; it’s inventory. Review comments are edits, not attacks.
I wrote long Slack threads instead of a 5‑minute call. Sometimes async is efficient; sometimes it’s procrastination in a trench coat.
I copied a regex from Stack Overflow without a test case. I won’t describe what broke; therapy helped. Regex gets tests now.
I ignored observability because the MVP ‘wasn’t ready for metrics yet’. Prod was ready for incidents; logs arrived one panic too late.
I said yes to scope creep because saying no felt rude. Boundaries aren’t rudeness—they’re how quality survives contact with reality.
I compared my chapter one to someone else’s chapter twelve. Useful for humility; useless for planning. Run your own race with your own constraints.
I once treated a Friday deploy as ‘just a small config tweak’ with no rollback story. The weekend re-taught me that ‘small’ and ‘safe’ are different words. Now Fridays respect blast radius.
Past me loved optimizing queries I hadn’t measured yet. These days I log first, prove the pain, then buy performance with real numbers—not vibes.
I used to skip tests when I was ‘in the zone’. The zone lied; prod didn’t. Tests are how I stay honest when confidence feels free.
I assumed stakeholders read the doc if I linked it once. They were busy; I was naive. A one-line summary beats a perfect PDF nobody opens.
I’ve nuked calm afternoons with a cheerful `git push --force` on shared branches. Branches are multiplayer; I treat shared history like glassware now.
I shipped ‘one more feature’ before fixing onboarding friction. Users don’t applaud features they never reach—clarity beats breadth on week one.
I learned that retries without backoff are just polite DDoS machines aimed at myself. Backoff, jitter, idempotency—boring words, quiet weekends.
I used to debate architecture in my head for days instead of sketching a box diagram for twenty minutes. Paper is cheaper than rewrite season.
I once waited too long to say ‘this timeline is fiction’. Silence felt kind; it wasn’t. Early honesty is respect, not pessimism.
I trusted env var names from memory across environments once. One typo taught me that ‘works on my machine’ should never be the only oracle.
I treated caching as free speed until stale data embarrassed me in front of users. Cache is a contract: who invalidates, when, and how loudly.
I merged without a rollback checklist because the release felt easy. Easy releases are exactly when the weird edge cases throw a party.
I’ve defended my code like it was my pet. Code isn’t identity; it’s inventory. Review comments are edits, not attacks.
I wrote long Slack threads instead of a 5‑minute call. Sometimes async is efficient; sometimes it’s procrastination in a trench coat.
I copied a regex from Stack Overflow without a test case. I won’t describe what broke; therapy helped. Regex gets tests now.
I ignored observability because the MVP ‘wasn’t ready for metrics yet’. Prod was ready for incidents; logs arrived one panic too late.
I said yes to scope creep because saying no felt rude. Boundaries aren’t rudeness—they’re how quality survives contact with reality.
I compared my chapter one to someone else’s chapter twelve. Useful for humility; useless for planning. Run your own race with your own constraints.
I once treated a Friday deploy as ‘just a small config tweak’ with no rollback story. The weekend re-taught me that ‘small’ and ‘safe’ are different words. Now Fridays respect blast radius.
Past me loved optimizing queries I hadn’t measured yet. These days I log first, prove the pain, then buy performance with real numbers—not vibes.
I used to skip tests when I was ‘in the zone’. The zone lied; prod didn’t. Tests are how I stay honest when confidence feels free.
I assumed stakeholders read the doc if I linked it once. They were busy; I was naive. A one-line summary beats a perfect PDF nobody opens.
I’ve nuked calm afternoons with a cheerful `git push --force` on shared branches. Branches are multiplayer; I treat shared history like glassware now.
I shipped ‘one more feature’ before fixing onboarding friction. Users don’t applaud features they never reach—clarity beats breadth on week one.
I learned that retries without backoff are just polite DDoS machines aimed at myself. Backoff, jitter, idempotency—boring words, quiet weekends.
I used to debate architecture in my head for days instead of sketching a box diagram for twenty minutes. Paper is cheaper than rewrite season.
I once waited too long to say ‘this timeline is fiction’. Silence felt kind; it wasn’t. Early honesty is respect, not pessimism.
I trusted env var names from memory across environments once. One typo taught me that ‘works on my machine’ should never be the only oracle.
I treated caching as free speed until stale data embarrassed me in front of users. Cache is a contract: who invalidates, when, and how loudly.
I merged without a rollback checklist because the release felt easy. Easy releases are exactly when the weird edge cases throw a party.
I’ve defended my code like it was my pet. Code isn’t identity; it’s inventory. Review comments are edits, not attacks.
I wrote long Slack threads instead of a 5‑minute call. Sometimes async is efficient; sometimes it’s procrastination in a trench coat.
I copied a regex from Stack Overflow without a test case. I won’t describe what broke; therapy helped. Regex gets tests now.
I ignored observability because the MVP ‘wasn’t ready for metrics yet’. Prod was ready for incidents; logs arrived one panic too late.
I said yes to scope creep because saying no felt rude. Boundaries aren’t rudeness—they’re how quality survives contact with reality.
I compared my chapter one to someone else’s chapter twelve. Useful for humility; useless for planning. Run your own race with your own constraints.
today's pick
Yesterday's me
Contact
Let's work together
Tell me a bit about what you need (project scope, timeline, or how I can help). I read every message and usually reply within a few days.
Top Rated · 100% Job Success
If you prefer hiring or messaging through a marketplace, I’m also on Upwork; that can be easier for contracts and milestones.
Hire me on Upwork