UmurInan
Blog Blog

Latest Blog Posts

Notes from production. Backend, databases, distributed systems, and the failure modes you only see at scale.

Filter:
Database

Posted on Jun 3, 2026

Postgres Won the Database War. Now What?

Postgres passed MySQL on the Stack Overflow survey. 'Postgres for everything' became the default. Where that gravity helps, where it quietly stops, and my rule.

Read more
Backend

Posted on Jun 2, 2026

You're Running Kafka for Three Topics

Kafka is a commit log for high-throughput streaming. Three topics at 10 msg/sec is not that. The operational tax you didn't price, and the tool that fits.

Read more
Backend

Posted on Jun 1, 2026

REST vs GraphQL Is Over. You're Now Running Both, Badly.

REST vs GraphQL got declared a tie: use both. Nobody costs that out. Two contracts, the HTTP caching you lost, a leaky BFF, and the N+1 that just moved.

Read more
Database

Posted on May 31, 2026

DuckDB Ate Your Analytics Pipeline and That's Fine

Most 'big data' analytics is tens of gigabytes, not terabytes. DuckDB runs it on one node in seconds, no cluster. When single-node wins and where it bites.

Read more
Tools

Posted on May 30, 2026

The RAG Pipeline That Confidently Made Things Up

A RAG assistant gave a confident, well-cited answer that was pure fiction. Why retrieval success is not grounding, and why the eval set is the only real fix.

Read more
Backend

Posted on May 29, 2026

Server-Sent Events Are Back. You Should Use Them.

Server-Sent Events made a quiet comeback because of LLM streaming. SSE vs WebSocket, the HTTP/1.1 connection trap, and the cases where SSE is the right call.

Read more
Backend

Posted on May 28, 2026

Why Your Distributed Lock Doesn't Lock

Distributed locks don't provide mutual exclusion. Fencing tokens, GC pauses, clock drift, and why the lock you wrote is actually a polite hint at best.

Read more
Tools

Posted on May 27, 2026

The Day Our LLM Bill Hit $40k

A weekend, a retry loop, and an Anthropic API key. How $40k of LLM cost happened in 60 hours, and the five-line policy that would have prevented all of it.

Read more
Tools

Posted on May 26, 2026

Claude Code vs Cursor: Six Months of Both

Six months running Cursor and Claude Code side by side. Where each one wins, where they don't compete, and the design choice that made me drop Cursor.

Read more
Database

Posted on May 26, 2026

pgvector at 10 Million Rows Is a Different Animal

pgvector is great at 100k rows. At 10 million it's a different animal. IVFFlat vs HNSW, storage math, the quantization escape, and what actually breaks.

Read more
Tools

Posted on May 26, 2026

Your AI Agent Isn't Broken. Your Evals Are.

Your AI agent isn't broken in some mysterious way. You just don't have evals. Why 'works on the demo' is the most expensive sentence in your AI roadmap.

Read more
Backend

Posted on May 24, 2026

The Kafka Consumer Group That Stopped Consuming

A Kafka consumer group can stop consuming while every metric looks healthy. Rebalance storms, max poll timeouts, stuck partitions, and how to actually diagnose.

Read more
Backend

Posted on May 23, 2026

The Postgres Index That Never Gets Used

Postgres indexes accumulate. Every perf push adds one. Almost no team removes any. How to find the unused ones and why their write cost is the bigger problem.

Read more
Thinking

Posted on May 22, 2026

AI Code Review Is Mostly Noise

AI code reviewers are the hot dev-tool category of 2026. After months of real use on a review queue, the signal-to-noise ratio is bad. Here are the numbers.

Read more
Backend

Posted on May 21, 2026

The Endpoint That Always Returns 200

REST APIs that wrap every error in HTTP 200 break retries, caches, load balancers, circuit breakers, and observability. The status code is part of the contract.

Read more
Devops

Posted on May 20, 2026

DNS Is Always the Answer

It really is always DNS. TTL caches, resolver storms, NXDOMAIN under load, split-horizon traps, SNI mismatches. The actual failure modes behind the meme.

Read more
Backend

Posted on May 19, 2026

Open Session in View Is Spring Boot's Quietest Footgun

Spring Boot ships with Open Session in View on by default. Lazy loading from controllers, hidden N+1s, JDBC connections pinned for the whole HTTP request.

Read more
Backend

Posted on May 18, 2026

Four Spring Boot 4 Features That Actually Change Your Code

Spring Boot 4 release notes are long. Four features change how you actually write code: API versioning, HTTP service clients, virtual threads, RestTestClient.

Read more
Backend

Posted on May 17, 2026

The Long Transaction That Ate Your Postgres

An idle transaction pins the xmin horizon. Autovacuum cannot reclaim anything newer than it. Tables bloat. Queries slow. Here is the fix every install needs.

Read more
Thinking

Posted on May 16, 2026

Your AI Coding Speedup Is Not What You Think

AI coding tools promise a 10x speedup. After a year of daily Claude Code use, the real number on a real codebase is closer to 1.5x. Here is what I measure.

Read more
Backend

Posted on May 15, 2026

Sagas Are Not Transactions

Sagas replace ACID transactions with compensation actions, not rollbacks. Intermediate states are visible to other services, and compensations can fail too.

Read more
Backend

Posted on May 14, 2026

Checked Exceptions Were a Mistake and Spring Proved It

Checked exceptions force callers to acknowledge errors, not handle them. Spring's unchecked hierarchy and the @Transactional rollback default show the cost.

Read more
Backend

Posted on May 13, 2026

Your Spring Bean Is Not What You Think It Is

Spring's default bean scope is singleton. The bugs appear when a service holds mutable state, a scoped bean is misused, or ThreadLocal cleanup is skipped.

Read more
Backend

Posted on May 12, 2026

Your Equals and HashCode Are Wrong

Hibernate entities in a Set stop being findable after you persist them. equals and hashCode based on a null id change the moment the database assigns a value.

Read more
Backend

Posted on May 11, 2026

Your JWT Is Not a Session

JWTs cannot be revoked, permissions inside them go stale, and clocks drift. The failure modes that appear when you treat a signed token like a session.

Read more
Backend

Posted on May 10, 2026

Hibernate's ddl-auto Is Not a Migration Tool

ddl-auto: update silently adds columns and never drops them. What it does to your schema, why it fails on renames, and how to safely replace it with Flyway.

Read more
Backend

Posted on May 9, 2026

Your Replica Is Lying To You

Read replicas trade staleness for throughput. Replication lag, read-your-writes, and the staleness window nobody tracks: these are where things actually break.

Read more
Practices

Posted on May 8, 2026

The Test That Passes When Prod Is Broken

Your unit tests are mostly testing your mocks. When the mock drifts from the real dependency, tests pass and prod breaks. The fix is harder than it looks.

Read more
Devops

Posted on May 7, 2026

Your Logs Are a Pile, Not a System

Log levels exist for a reason. Most codebases ignore the reason, log everything at INFO, then wonder why the logs are useless during an actual incident.

Read more
Backend

Posted on May 6, 2026

UTC In the Database Was the Easy Part

Storing UTC is the easy part. Display, recurring events, DST, date-only fields, and scheduled jobs: the real bugs live in the conversion layer, not the storage.

Read more
Backend

Posted on May 4, 2026

Your Async Code Is Still Single-Threaded

Async lets one thread do more I/O. It does not let one thread do more CPU. Most async-related performance disappointments come from confusing those two.

Read more
Backend

Posted on May 1, 2026

Two Transactions Walk Into a Lock

Deadlocks are not exotic. They are predictable consequences of lock order. Here are the patterns, the fixes, and the eleven characters that ended one outage.

Read more
Practices

Posted on Apr 30, 2026

Nobody Reads a 1,000-Line Diff

The math on PR review quality is brutal. Past 400 lines, defect detection collapses, approvals get rubber-stamped, and your review process is theatre.

Read more
Backend

Posted on Apr 29, 2026

The Cache-Control Header You're Probably Ignoring

Most developers set max-age and call it done. The directives that matter for CDN behavior, revalidation, and stale content are all sitting there unused.

Read more
Backend

Posted on Apr 28, 2026

Why Your Service Slows Down at 9am Every Day

Your service slows every morning for the same five reasons: JVM warmup, cold caches, pool growth, clustered crons, deployment timing. Here's how to fix each.

Read more
Backend

Posted on Apr 27, 2026

Spring Boot Auto-Configuration Is Magic Until It Isn't

Spring Boot configures your app without a line of config. Then it configures something you did not want. Here is how the mechanism works and how to control it.

Read more
Backend

Posted on Apr 26, 2026

CQRS Sounds Fancy Until You Have to Debug It

CQRS separates reads from writes but not bugs from confusion about which side caused them. Here is when the pattern helps and when it just adds complexity.

Read more
Backend

Posted on Apr 25, 2026

The Composite Index Nobody Can Read

Your composite index covers every column but EXPLAIN still shows a full scan. Column order, not column presence, determines whether PostgreSQL uses the index.

Read more
Backend

Posted on Apr 24, 2026

The Hibernate Query You Didn't Write

Hibernate writes SQL you never see. Three repository lines execute a 2,100-character query that is usually worse than anything you would have written by hand.

Read more
Backend

Posted on Apr 21, 2026

Database Isolation Levels Are a Contract, Not a Dial

Isolation levels define which anomalies you tolerate, not how much correctness you get. The SQL standard and what databases implement diverged decades ago.

Read more
Backend

Posted on Apr 19, 2026

The NULL Trap

NULL is a three-valued logic system that corrupts aggregations, breaks NOT IN subqueries, and hides rows from WHERE clauses. It is not just a missing value.

Read more
Backend

Posted on Apr 19, 2026

The Thundering Herd Problem

Cache stampedes, retry storms, reconnect floods: three failure modes with the same root cause. Synchronized behavior under load amplifies failures every time.

Read more
Backend

Posted on Apr 17, 2026

EXPLAIN ANALYZE Lies to You

PostgreSQL's EXPLAIN ANALYZE tells you the plan looks fast. It doesn't tell you the timing is cached, the estimates are stale, or the cost isn't milliseconds.

Read more
Backend

Posted on Apr 16, 2026

Database Partitioning: The Decision You Can't Undo

Range vs hash partitioning, hot spots, and the re-partitioning trap. Partitioning looks like a scaling win until you find out you cannot undo the choice.

Read more
Backend

Posted on Apr 15, 2026

Connection Pool Tuning: A Practical Guide

HikariCP's defaults look sensible until your app hits production load. Here's how to actually size your connection pool using Little's Law, not guesswork.

Read more
Backend

Posted on Apr 14, 2026

Webhook Reliability: The Lost Art

Webhooks break predictably: duplicate events, missed deliveries, retry storms. Here is what it actually takes to build receivers that hold up in production.

Read more
Backend

Posted on Apr 12, 2026

@Transactional Is Not Magic

@Transactional looks simple until you hit self-invocation, wrong exception types, or silent failures on private methods. Here's what it actually does.

Read more
Backend

Posted on Apr 12, 2026

Transactions Don't Fix Race Conditions

Wrapping code in a transaction doesn't make concurrent operations safe. Here's what transactions guarantee and what race conditions they let slip through.

Read more
Practices

Posted on Apr 11, 2026

Good Enough Is a Strategy

In engineering, perfectionism is often procrastination disguised as craftsmanship. Shipping an 80% solution and iterating beats a perfect solution shipped late.

Read more
Backend

Posted on Apr 10, 2026

Soft Deletes Are a Trap

Adding is_deleted to your tables feels harmless. Here's what it actually costs: broken constraints, query pollution, index bloat, and cascading confusion.

Read more
Backend

Posted on Apr 9, 2026

The Java Terminology Survival Guide

Java EE, Jakarta EE, javax, SE, JDK, JRE, OpenJDK, Spring Boot, Spring MVC. A plain-language guide to every confusing name in the entire Java ecosystem.

Read more
Backend

Posted on Apr 8, 2026

The Outbox Pattern: Reliable Events Without Two-Phase Commit

Reliable event publishing alongside database writes is harder than it looks. The transactional outbox pattern solves it without distributed transactions.

Read more
Backend

Posted on Apr 7, 2026

Event Sourcing Sounds Better Than It Is

Event sourcing promises auditability, time travel, and decoupled systems. The operational complexity arrives later, and most teams are not ready for it.

Read more
Backend

Posted on Apr 6, 2026

Rate Limiting Is Harder Than It Looks

Token bucket, sliding window, fixed counter: rate limiting algorithms all sound simple until you actually implement them correctly across distributed systems.

Read more
Backend

Posted on Apr 5, 2026

Distributed Transactions Are a Lie

Why two-phase commit fails in production distributed systems, and what engineers actually use instead: sagas, the outbox pattern, and eventual consistency.

Read more
Practices

Posted on Apr 3, 2026

Premature Abstraction Is Worse Than Duplication

DRY is right, but not yet. Three identical code blocks are better than one wrong abstraction that fights you for months. Wait until the pattern is obvious.

Read more
Backend

Posted on Apr 2, 2026

The Database Is Not Your Message Queue

Polling a status column every few seconds works until it does not. Here is why your database makes a terrible message queue and what to reach for instead.

Read more
Devops

Posted on Apr 1, 2026

Monitoring Is Not a Dashboard

Real monitoring is not a Grafana dashboard. It is knowing which questions to ask, which signals answer them, and what to do when the answer is unexpected.

Read more
Thinking

Posted on Mar 31, 2026

The Senior Engineer's Job Is to Say No

Knowing what not to build is more valuable than knowing how to build it. The hardest skill I learned as a senior engineer had nothing to do with code.

Read more
Backend

Posted on Mar 30, 2026

Caching Is Easy Until It Isn't

Redis, in-memory, CDN: caching feels simple until invalidation ruins your week. Here's how each caching layer bites you and what I learned the hard way.

Read more
Devops

Posted on Mar 29, 2026

The Deploy That Took Down Friday

Friday deploys have a reputation for a reason. Here's why they go wrong, what guardrails actually help, and when it's okay to ship on a Friday anyway.

Read more
Backend

Posted on Mar 28, 2026

Connection Pools: The Thing You Never Think About Until Production Burns

Connection pools sit quietly until they break. Here is what happens when they fail, the warning signs to watch, and how to catch it before production burns.

Read more
Thinking

Posted on Mar 28, 2026

Healthcare AI Has an Engineering Problem

Healthcare AI fails not because the models are bad, but because the surrounding software is. A software engineer's take on why it is harder than it looks.

Read more
Backend

Posted on Mar 27, 2026

Database Indexes Explained for People Who Keep Forgetting

You've read about database indexes before. You've forgotten most of it. Here's the practical guide you'll actually remember, with PostgreSQL examples.

Read more
Backend

Posted on Mar 26, 2026

Spring Boot Security Is Hard and That's Okay

Spring Security has a brutal learning curve. The filter chain is confusing, the docs assume too much, and 403 errors haunt your dreams. But it's worth it.

Read more
Backend

Posted on Mar 23, 2026

The Monolith That Works Fine, Thanks

Monoliths aren't a sign of technical immaturity. Most teams don't need microservices. Here's why a well-structured monolith is often the smarter choice.

Read more
Thinking

Posted on Mar 22, 2026

Why Most Technical Debates Don't Matter

Tabs vs spaces. REST vs GraphQL. Monolith vs microservices. Some technical debates matter, but most don't. Here's how I tell the difference after a decade.

Read more
Thinking

Posted on Mar 21, 2026

Vibe Coding Is Not Engineering

Vibe coding has its place. But the gap between prompting an AI until something works and actually engineering reliable software is wider than people think.

Read more
Thinking

Posted on Mar 18, 2026

I Spent a Week on Moltbook, the Social Network Where Only AI Agents Can Post

I browsed Moltbook for a week to see what AI agents actually talk about when humans can't participate. Some of it was fascinating. A lot of it was weird.

Read more
Tools

Posted on Feb 25, 2026

I Gave My AI Agent Access to My Life. Here's What Happened

I connected OpenClaw to WhatsApp, iMessage, and my browser with scheduled heartbeats. Here is what living with an always-on AI agent for a week looks like.

Read more
Mobile

Posted on Feb 20, 2026

SwiftUI vs Jetpack Compose: A Side-by-Side Comparison From Someone Who Uses Both Daily

I maintain the same app on iOS and Android. Here's how SwiftUI and Jetpack Compose actually compare when you ship features across both platforms weekly.

Read more
Tools

Posted on Feb 18, 2026

Debugging iOS Memory Issues from Your AI Chat Interface

I built an MCP server that lets Claude inspect iOS simulators from the chat window. Crash analysis, memory risk scoring, log streaming, and leak detection.

Read more
Tools

Posted on Feb 18, 2026

I Use Slack to Boss Around My Local Claude Code Terminal (And It's Glorious)

How I wired up Slack as a remote control for my local Claude Code terminal. I can send coding prompts from my phone, from a meeting, or anywhere else.

Read more
Backend

Posted on Feb 15, 2026

Why Component-Based Structure Beats Traditional Package-by-Layer in Java

Why organizing Java code by feature instead of by layer (controller/service/repository) gives you better modularity, easier navigation, and real encapsulation.

Read more
Tools

Posted on Feb 15, 2026

How I Use MCP Agents, Skills, and Subagents to Build Software Faster

My actual workflow with Claude Code's MCP servers, custom agents, and skills across Spring Boot, iOS, and Android. Real examples from production code.

Read more
Tools

Posted on Feb 14, 2026

How MCP Servers Supercharge My AI Development Workflow

The four MCP servers I use daily with Claude Code: Firebase, Notion, Context7, Greptile. What each one does, how to set them up, how they work together.

Read more
Thinking

Posted on Feb 12, 2026

The Dunning-Kruger Effect: Why Incompetence Feels Like Confidence

People with limited skill overestimate their ability while experts underestimate theirs. Here is how the Dunning-Kruger effect shows up in engineering teams.

Read more
Practices

Posted on Feb 12, 2026

Git Best Practices for Modern Engineering Teams

A visual guide to Git branching: staging vs production setups, GitFlow vs Trunk-Based Development, and the commands that matter, with diagrams and examples.

Read more
Tools

Posted on Feb 11, 2026

How I Use Claude Code Terminal to Supercharge My Development Workflow

Patterns from months of daily Claude Code use: parallel tasks, MCP integrations, git workflow automation, and tips for getting consistent real-world value.

Read more