blog

learning things, building things, breaking things, writing about it. technical projects, personal struggles, life stuff, random observations - just documenting whatever I'm working through.

Four Reasonable Decisions and a Dead Feed

Four Reasonable Decisions and a Dead Feed

Every page on this blog advertised an RSS feed that returned 404. No single line of code was wrong — four independently sensible decisions composed into a file that existed only inside a CI runner. Plus a cross-domain sitemap, a verification file an SPA can fake, and what Hugo, Astro and Eleventy do differently.

Documentation That Outlived Its Code

Documentation That Outlived Its Code

Every doc in this repo described a site that no longer existed — a terminal aesthetic replaced a year ago and a colour system reduced to an identity function. Auditing them turned up 60 lines of configuration that no code reads.

[object Object]: How One Dependabot Bump Broke 34 of 39 Posts

[object Object]: How One Dependabot Bump Broke 34 of 39 Posts

A major bump to marked changed every renderer method to take a token object instead of positional strings. The build kept exiting 0 while emitting the literal text [object Object] into 34 of 39 posts — and a missing curl flag nearly convinced me nothing was wrong.

The Two-Month Outage: Dead DNS, Eager Filters, and Two Kinds of Postgres URL

The Two-Month Outage: Dead DNS, Eager Filters, and Two Kinds of Postgres URL

scalable-chat-platform was down for two months and I did not notice. A free-tier Postgres powered off, its DNS record vanished, and a servlet filter took the whole app down with it — including the health endpoint that was supposed to tell me. Now with the Render-side postmortem: a 59-day hole in the deploy history, an empty healthCheckPath, and one of my own conclusions falsified.

HikariCP Exhaustion, Connection Hogging, and Optimistic Locking

HikariCP Exhaustion, Connection Hogging, and Optimistic Locking

Phase 2 of the spring-validation-lab: REQUIRES_NEW against a saturated pool, HTTP inside @Transactional after first SQL, and @Version under flash contention — all proven with H2 tests.

Spring Bean Lifecycle, Circular Deps, and Mini-Umbrellas

Spring Bean Lifecycle, Circular Deps, and Mini-Umbrellas

Phase 1 wrap: @PostConstruct runs before the AOP proxy; constructor cycles fail to boot; Spring Data invents mini-transactions when you have no outer @Transactional.

Spring ThreadLocals and @Async: What We Proved

Spring ThreadLocals and @Async: What We Proved

Phase 1 continued: SecurityContext lives in a ThreadLocal by default. Naive @Async loses Authentication (not the context object). Explicit args and DelegatingSecurityContextRunnable fixes.

Spring Proxies and Self-Invocation: What We Proved

Spring Proxies and Self-Invocation: What We Proved

Phase 1 of the spring-validation-lab: @Transactional is a sticky note read by a proxy. Self-invocation makes REQUIRES_NEW dead text. Broken and fixed designs, asserted with H2.

Proving Spring Internals With Tests (Not Folklore)

Proving Spring Internals With Tests (Not Folklore)

Series hub: a Java 21 / Spring Boot 4.1 lab where broken and fixed Spring designs are proven with H2 tests. Deep dives for proxies, ThreadLocals, lifecycle, and HikariCP.

Hardening the Chat Platform: Deps, Deep Health, and CI Pings

Hardening the Chat Platform: Deps, Deep Health, and CI Pings

Merged five Dependabot frontend PRs, fixed React 19 + Docker builds, opened actuator health for probes, and added caching and rate limits—then moved scheduled pings into the app repo so nothing doubles up.