David John Thammineni

Blog

88 posts on AI engineering, React, TypeScript, and the craft of modern frontend — published since 2020.

2026

16 posts
The useEffect Chain Reaction: Derived State and the Effects You Don't Need
React13 Jul 20267 min read

The useEffect Chain Reaction: Derived State and the Effects You Don't Need

An analytics filter panel re-rendered eleven times per click, flashed stale charts, and had a bug nobody could reproduce twice. The root cause: state that should have been math, wired together with effects.

Streaming That Doesn't Stream: Fixing Suspense Waterfalls in Next.js
Performance12 Jul 20267 min read

Streaming That Doesn't Stream: Fixing Suspense Waterfalls in Next.js

An insurance quote flow used Suspense everywhere and still loaded like 2015 — sequential awaits, one giant loading.tsx, and a hidden auth check were serializing everything. Anatomy of a streaming rescue.

"use client" Creep: How Our Server-First App Quietly Became a 1.2MB SPA
Next.js11 Jul 20267 min read

"use client" Creep: How Our Server-First App Quietly Became a 1.2MB SPA

Nobody decides to ship a megabyte of JavaScript — it happens one convenient directive at a time. Auditing a customer portal that drifted from server-first to client-everything, and the boundary discipline that reversed it.

The Dashboard That Died Every Night: Hunting React Memory Leaks
Performance10 Jul 20267 min read

The Dashboard That Died Every Night: Hunting React Memory Leaks

An operations wallboard that ran 24/7 crashed every night around 3am. Heap snapshots, detached DOM trees, and the five leak patterns that survive code review — a forensic walkthrough.

Maximum Update Depth Exceeded: A Field Guide to Infinite Render Loops
React09 Jul 20267 min read

Maximum Update Depth Exceeded: A Field Guide to Infinite Render Loops

A drag-and-drop form builder froze the browser tab every time two specific widgets coexisted. Tracing it taught me the four species of infinite render loop — and the object-identity discipline that prevents all of them.

The Search Box That Showed the Wrong Results: Effect Race Conditions
React08 Jul 20267 min read

The Search Box That Showed the Wrong Results: Effect Race Conditions

In a 3D asset library search, typing 'bracket' sometimes showed results for 'brack'. Out-of-order responses are the most-shipped bug in React data fetching — here's the anatomy and the three-tier fix.

"Functions Cannot Be Passed to Client Components": Surviving the RSC Boundary
Next.js07 Jul 20267 min read

"Functions Cannot Be Passed to Client Components": Surviving the RSC Boundary

Migrating a 200-component design system to Server Components turned one cryptic error into a daily ritual. Here's the mental model of the serialization boundary — and the composition patterns that make it stop hurting.

Stale Closures: Why Your WebSocket Handler Sees State From the Past
React05 Jul 20267 min read

Stale Closures: Why Your WebSocket Handler Sees State From the Past

A clinical-trial monitoring dashboard kept alerting on thresholds users had already changed. The culprit: every long-lived callback in React is a time capsule, and ours were sealed at mount.

Next.js Served Yesterday's Prices: Untangling the Four Caching Layers
Next.js05 Jul 20267 min read

Next.js Served Yesterday's Prices: Untangling the Four Caching Layers

A pharma ordering portal showed stale prices for 19 hours after a repricing event. The bug wasn't in our code — it was in the four overlapping caches between the database and the pixel.

Hydration Mismatches: Debugging React's Most Passive-Aggressive Error
React04 Jul 20267 min read

Hydration Mismatches: Debugging React's Most Passive-Aggressive Error

A trading dashboard that only broke for users in Sydney taught me everything about hydration mismatches — timezones, random IDs, browser extensions, and the third-party script that gaslit us for a week.

Designing AI-Native Interfaces
AI Engineering24 Jun 20264 min read

Designing AI-Native Interfaces

The chat box was AI's MVP. The real work is the interface around the model: streaming as a design material, agents that render state instead of messages, and provenance as a UI affordance.

From RAG to Agents: The LLM Product Stack in 2026
AI Engineering12 May 20265 min read

From RAG to Agents: The LLM Product Stack in 2026

Model routers, hybrid retrieval, agentic state machines, and evals-as-CI - a working map of the modern LLM stack, and why the experience layer is the moat.

Tokens per Interaction: The Web Vital Nobody Is Tracking Yet
AI Engineering16 Apr 20263 min read

Tokens per Interaction: The Web Vital Nobody Is Tracking Yet

We track bytes, milliseconds, and layout shift - but AI products burn tokens invisibly. Instrumenting TPI, setting budgets per feature, and the regressions we caught.

AI Features on a Static Site: Edge Functions and Client Models
Performance19 Mar 20263 min read

AI Features on a Static Site: Edge Functions and Client Models

You don't need a server to ship AI features. Edge streaming proxies, WebGPU embeddings in the browser, and keeping the static-site speed you paid for.

Context Engineering: The Discipline Formerly Known as Prompting
AI Engineering19 Feb 20263 min read

Context Engineering: The Discipline Formerly Known as Prompting

The prompt was never the hard part - the context is. Budgeting tokens like a performance budget, structuring for salience, and measuring what the model actually uses.

Model Routing in Anger: A Production Architecture
AI Engineering22 Jan 20263 min read

Model Routing in Anger: A Production Architecture

Route by task class, escalate on verification failure, and treat model choice as config. The router that cut our costs 68% without a quality regression.

2025

12 posts
2025 in Review: The Year Agents Got Boring (Complimentary)
AI Engineering18 Dec 20253 min read

2025 in Review: The Year Agents Got Boring (Complimentary)

Agents went from demos to line items: what shipped, what stalled, and the patterns that survived contact with production.

Guardrails in Depth: Designing for Prompt Injection
AI Engineering13 Nov 20253 min read

Guardrails in Depth: Designing for Prompt Injection

Injection isn't solved and won't be. The lethal trifecta, capability-based defenses, and the layers that make attacks expensive instead of impossible.

Agent Memory: Checkpointing State for Long-Running Work
AI Engineering16 Oct 20253 min read

Agent Memory: Checkpointing State for Long-Running Work

Agents that work for hours need durable state, resumability, and memory that survives the context window. The checkpoint architecture that works.

Tailwind CSS v4: CSS-First Config and the 100x Faster Engine
CSS11 Sept 20252 min read

Tailwind CSS v4: CSS-First Config and the 100x Faster Engine

The JS config file is gone, design tokens live in @theme, and builds are near-instant. Migration notes and the details that surprised us.

Generative UI: Streaming Components, Not Markdown
AI Engineering14 Aug 20253 min read

Generative UI: Streaming Components, Not Markdown

The model picks the component, your code renders it. Tool-call-driven UI with streamUI, schema-constrained props, and where to draw the line.

Evals Are CI: The Discipline That Separates AI Teams
AI Engineering17 Jul 20253 min read

Evals Are CI: The Discipline That Separates AI Teams

Prompt edits, model swaps, retrieval tweaks - every change runs the eval suite or it doesn't merge. The maturity ladder from vibes to regression gates.

Browser Agents: Automating the Web That Has No API
AI Engineering19 Jun 20253 min read

Browser Agents: Automating the Web That Has No API

Computer-use models can drive real UIs now. Where browser agents beat RPA, the reliability engineering they need, and the guardrails they demand.

Hybrid Retrieval and Rerankers: The RAG Upgrade With Receipts
AI Engineering15 May 20253 min read

Hybrid Retrieval and Rerankers: The RAG Upgrade With Receipts

Vectors miss exact matches, BM25 misses paraphrases, and RRF fusion plus a reranker fixes both. Measured on our eval set: recall@5 from 64% to 89%.

React 19's use() Hook: Suspense-First Data in Client Components
React24 Apr 20252 min read

React 19's use() Hook: Suspense-First Data in Client Components

use() reads promises in render, works conditionally, and pairs with server-started promises for clean streaming. Patterns and the pitfall.

MCP Servers in Production: Auth, Scoping, and Audit
AI Engineering13 Mar 20253 min read

MCP Servers in Production: Auth, Scoping, and Audit

OpenAI adopted MCP and the protocol won. Now the real work: building capability servers that are safe to point an agent at.

Working with Coding Agents: A Senior Engineer's Workflow
AI Engineering20 Feb 20253 min read

Working with Coding Agents: A Senior Engineer's Workflow

Agentic coding tools now handle multi-file tasks with a plan-review-execute loop. What to delegate, what to keep, and how code review changes.

LLM Cost Engineering After DeepSeek: Cheap Is a Capability
AI Engineering30 Jan 20253 min read

LLM Cost Engineering After DeepSeek: Cheap Is a Capability

DeepSeek-R1 reset the price of reasoning. Cascade routing, output-token discipline, and the cost dashboard every AI product needs.

2024

12 posts
AI Code Review That Developers Don't Ignore
AI Engineering12 Dec 20243 min read

AI Code Review That Developers Don't Ignore

LLM reviewers drown PRs in nitpicks unless you design against it. Diff-scoped context, confidence thresholds, and measuring the signal-to-noise ratio.

MCP: A USB Port for AI Context
AI Engineering28 Nov 20243 min read

MCP: A USB Port for AI Context

Anthropic's Model Context Protocol standardizes how assistants reach tools and data. Building a server in 40 lines, and why the M-by-N problem needed this.

React 19 RC: The Compiler Retires useMemo
React17 Oct 20243 min read

React 19 RC: The Compiler Retires useMemo

Automatic memoization, Actions with useActionState, use(), and ref as a prop. What React 19 deletes from your codebase.

o1 and Reasoning Models: When Thinking Time Is Worth It
AI Engineering19 Sept 20242 min read

o1 and Reasoning Models: When Thinking Time Is Worth It

OpenAI's o1 spends tokens thinking before answering. Where the tradeoff pays - planning, math, hard debugging - and where GPT-4o remains the right call.

Prompt Caching: The Easiest 80% Cost Cut You'll Ship This Year
AI Engineering22 Aug 20243 min read

Prompt Caching: The Easiest 80% Cost Cut You'll Ship This Year

Anthropic's prompt caching discounts repeated context by 90%. Structuring prompts for cache hits, and the ordering rule that makes or breaks it.

Multi-Agent Systems: Orchestrate, Don't Emerge
AI Engineering18 Jul 20242 min read

Multi-Agent Systems: Orchestrate, Don't Emerge

Planner-executor, generator-critic, and explicit handoffs beat autonomous agent swarms. Patterns from building a working document pipeline.

Structured LLM Outputs: Zod as the Contract
AI Engineering13 Jun 20243 min read

Structured LLM Outputs: Zod as the Contract

Schema-first generation with generateObject, retry-with-errors, and why your LLM boundary should look exactly like your API boundary.

GPT-4o and Practical Multimodal: Beyond the Demo
AI Engineering23 May 20243 min read

GPT-4o and Practical Multimodal: Beyond the Demo

Half the latency, half the price, and vision that's finally production-grade. Real use cases: document extraction, UI understanding, and screenshot-driven support.

Building an Eval Pipeline Before You Need It
AI Engineering11 Apr 20243 min read

Building an Eval Pipeline Before You Need It

Prompt changes without evals are refactors without tests. Golden datasets, LLM-as-judge with rubrics, and wiring it all into CI.

Multi-Model Strategy: What Claude 3 Changes
AI Engineering21 Mar 20243 min read

Multi-Model Strategy: What Claude 3 Changes

Claude 3 ends the single-vendor era: 200K context, vision, and Haiku's price point. The provider-abstraction layer every LLM product now needs.

The Vercel AI SDK: Streaming Chat UIs in an Afternoon
AI Engineering15 Feb 20242 min read

The Vercel AI SDK: Streaming Chat UIs in an Afternoon

useChat handles the streaming, state, and abort logic you were hand-rolling. Provider-agnostic backends and the patterns for production chat.

Server Actions: Forms Without the API Route
Next.js25 Jan 20242 min read

Server Actions: Forms Without the API Route

Mutations as plain functions, progressive enhancement for free, and useFormStatus for pending UI. Also: they're public endpoints - validate accordingly.

2023

12 posts
Running LLMs Locally with Ollama: What's Actually Usable
AI Engineering07 Dec 20232 min read

Running LLMs Locally with Ollama: What's Actually Usable

Mistral 7B on a MacBook is genuinely useful. Setup in two commands, the OpenAI-compatible dev loop, and honest expectations by model size.

The Assistants API: Convenience Now, Coupling Forever
AI Engineering16 Nov 20232 min read

The Assistants API: Convenience Now, Coupling Forever

OpenAI's new Assistants API bundles threads, retrieval, and code execution. What it saves you, what it costs you, and when to own the loop yourself.

htmx and the Case for Hypermedia: Not Every App Needs a SPA
JavaScript12 Oct 20232 min read

htmx and the Case for Hypermedia: Not Every App Needs a SPA

Attributes on HTML, partials from the server, and a 14KB budget. Where the hypermedia model beats the SPA - and where it doesn't.

Bun 1.0: Fast Is a Feature, Compatibility Is the Question
Tooling21 Sept 20233 min read

Bun 1.0: Fast Is a Feature, Compatibility Is the Question

Runtime, package manager, bundler, and test runner in one binary. Where Bun already wins, and where Node keeps the production crown for now.

RAG Quality Is Chunking Quality
AI Engineering17 Aug 20233 min read

RAG Quality Is Chunking Quality

Retrieval fails at the chunk level long before the model sees anything. Structure-aware splitting, overlap, context headers, and how to evaluate.

App Router Data Fetching: Cache Semantics You Need to Internalize
Next.js27 Jul 20232 min read

App Router Data Fetching: Cache Semantics You Need to Internalize

fetch caching, revalidate, dynamic rendering, and parallel data loading - the four decisions behind every fast App Router page.

Function Calling: GPT as an Intent Parser, Not a Guesser
AI Engineering15 Jun 20233 min read

Function Calling: GPT as an Intent Parser, Not a Guesser

OpenAI's function calling turns 'parse the user's request' into a schema contract. Structured extraction, tool dispatch, and the validation you still need.

Choosing a Vector Database: pgvector Until It Hurts
AI Engineering25 May 20233 min read

Choosing a Vector Database: pgvector Until It Hurts

Pinecone, Weaviate, Chroma, pgvector - the honest decision tree, plus the metadata-filtering and hybrid-search details that matter more than the benchmark.

LangChain in Production: What to Use, What to Skip
AI Engineering13 Apr 20232 min read

LangChain in Production: What to Use, What to Skip

After a quarter building with LangChain: the loaders and splitters earn their keep, the chains and agents you should probably write yourself.

Semantic Search with Embeddings: Beyond Keyword Matching
AI Engineering23 Mar 20233 min read

Semantic Search with Embeddings: Beyond Keyword Matching

Embeddings turn text into vectors where distance means similarity. Building search that understands 'reset my password' matches 'can't log in' - with cosine similarity from scratch.

Streaming LLM Responses with Server-Sent Events
AI Engineering09 Feb 20232 min read

Streaming LLM Responses with Server-Sent Events

A 5-second wall of latency becomes a live typing effect. Wiring OpenAI streaming through SSE to a React frontend, with cancellation.

React Server Components: The Mental Model That Finally Clicked
React19 Jan 20233 min read

React Server Components: The Mental Model That Finally Clicked

Stop thinking 'SSR but different.' Server Components are a component-granular split of your app across the network boundary.

2022

12 posts
TypeScript Narrowing: Discriminated Unions Over Boolean Flags
TypeScript08 Dec 20222 min read

TypeScript Narrowing: Discriminated Unions Over Boolean Flags

Model states as a union with a discriminant and impossible states stop compiling. The pattern, exhaustiveness checking, and typed API results.

Integrating GPT-3 into a Product: Lessons from the First Build
AI Engineering17 Nov 20223 min read

Integrating GPT-3 into a Product: Lessons from the First Build

We added GPT-3 drafting to a client's CRM. Prompt design, cost control, latency UX, and the failure modes nobody warns you about.

Next.js 13's App Directory: A First Look at the New Mental Model
Next.js27 Oct 20222 min read

Next.js 13's App Directory: A First Look at the New Mental Model

Server Components by default, layouts that don't re-render, and colocation of data with UI. What the beta gets right and what to wait on.

Astro and Islands: Shipping Zero JavaScript by Default
Performance15 Sept 20222 min read

Astro and Islands: Shipping Zero JavaScript by Default

Astro 1.0 renders everything to HTML and hydrates only the components you mark interactive. The islands model, client directives, and where it fits.

Playwright: E2E Tests That Don't Cry Wolf
Testing11 Aug 20222 min read

Playwright: E2E Tests That Don't Cry Wolf

Auto-waiting assertions, user-facing locators, and trace files that make failures debuggable. The patterns behind a flake-free suite.

React Native in 2022: Expo Grew Up
React Native21 Jul 20222 min read

React Native in 2022: Expo Grew Up

EAS Build, dev clients, and config plugins removed the old reasons to eject. How I structure a production Expo app now.

Shipping ESM in Node Without Breaking Everyone: A TS 4.7 Guide
Node.js16 Jun 20222 min read

Shipping ESM in Node Without Breaking Everyone: A TS 4.7 Guide

TypeScript 4.7 landed nodenext module resolution. What moduleResolution, exports maps, and .mts actually do, and a sane migration path.

tRPC: End-to-End Type Safety Without Writing a Schema
TypeScript26 May 20222 min read

tRPC: End-to-End Type Safety Without Writing a Schema

Define a procedure on the server, call it from the client, and TypeScript knows the types across the wire. How tRPC works and when to choose it over REST or GraphQL.

Zustand: State Management Without the Ceremony
React14 Apr 20222 min read

Zustand: State Management Without the Ceremony

A store in four lines, selector-based subscriptions, no providers. Why Zustand became my default for client state.

Upgrading to React 18: createRoot, StrictMode, and the Double-Effect Surprise
React31 Mar 20222 min read

Upgrading to React 18: createRoot, StrictMode, and the Double-Effect Surprise

React 18 is out. The upgrade is two lines - and then StrictMode runs your effects twice in dev and your bugs surface. That's a feature.

Container Queries: Components That Respond to Their Container
CSS10 Feb 20222 min read

Container Queries: Components That Respond to Their Container

Media queries know the viewport; components live in containers. @container finally lets a card adapt to the space it is actually given.

React 18's useTransition: Concurrent Rendering You Can Feel
React20 Jan 20222 min read

React 18's useTransition: Concurrent Rendering You Can Feel

Mark updates as non-urgent and React keeps the UI responsive while heavy renders happen in the background. Where transitions help and where they don't.

2021

12 posts
Core Web Vitals: A Field Guide to the Metrics That Now Rank You
Performance16 Dec 20212 min read

Core Web Vitals: A Field Guide to the Metrics That Now Rank You

Google's page experience rollout made LCP, FID, and CLS ranking signals. What each one actually measures and the fixes that move them.

Structuring a Frontend Monorepo with Nx
Tooling11 Nov 20212 min read

Structuring a Frontend Monorepo with Nx

Apps thin, libs fat, boundaries enforced by lint rules, and affected-only CI. The Nx setup that scaled to five apps and forty libraries.

Template Literal Types: Typing the Strings You Compose
TypeScript21 Oct 20212 min read

Template Literal Types: Typing the Strings You Compose

TypeScript 4.1+ can type route paths, event names, and CSS values built from string composition. Practical patterns, not type golf.

Incremental Static Regeneration: Static Speed, Fresh Data
Next.js09 Sept 20212 min read

Incremental Static Regeneration: Static Speed, Fresh Data

ISR rebuilds pages one at a time, on demand, in the background. How revalidate works, what stale-while-revalidate means for users, and fallback strategies.

esbuild: Why Your Next Build Tool Is Written in Go
Tooling19 Aug 20212 min read

esbuild: Why Your Next Build Tool Is Written in Go

esbuild bundles in milliseconds what webpack does in minutes. Where to adopt it today - and where its trade-offs say wait.

Suspense Boundaries: Designing Loading States That Don't Flicker
React08 Jul 20212 min read

Suspense Boundaries: Designing Loading States That Don't Flicker

Where you place Suspense boundaries is a UX decision. Nested boundaries, skeleton hierarchies, and avoiding the spinner cascade.

Node.js Streams: Processing a 2GB CSV Without Blowing the Heap
Node.js24 Jun 20212 min read

Node.js Streams: Processing a 2GB CSV Without Blowing the Heap

readFile on large files is a memory bomb. Streams process gigabytes in constant memory - here's the pipeline pattern with backpressure handled for you.

Dark Mode with CSS Custom Properties, Done Right
CSS13 May 20212 min read

Dark Mode with CSS Custom Properties, Done Right

Semantic design tokens, prefers-color-scheme with a manual override, and avoiding the flash of wrong theme.

Migrating from Create React App to Vite
Tooling22 Apr 20212 min read

Migrating from Create React App to Vite

Cold starts went from 28 seconds to under a second. The migration steps, the gotchas, and why native ESM makes it possible.

React Query: Stop Putting Server Data in Redux
React18 Mar 20212 min read

React Query: Stop Putting Server Data in Redux

Server state has different problems than client state - caching, staleness, refetching. React Query solves them in a way Redux never did.

Adopting Tailwind CSS in a Real Project: A Month In
CSS25 Feb 20212 min read

Adopting Tailwind CSS in a Real Project: A Month In

Utility-first looked like inline styles with extra steps. A month later the design system config and the deleted CSS files convinced me.

ES2021: The Features Worth Adopting Today
JavaScript14 Jan 20212 min read

ES2021: The Features Worth Adopting Today

replaceAll, Promise.any, logical assignment operators, and numeric separators - small additions that clean up everyday code.

2020

12 posts
A Service Worker Caching Strategy That Won't Bite You
Performance10 Dec 20202 min read

A Service Worker Caching Strategy That Won't Bite You

Cache-first for static assets, network-first for API calls, and the cache-versioning step everyone forgets until their users are stuck on old code.

React Context Without the Re-Render Tax
React19 Nov 20202 min read

React Context Without the Re-Render Tax

Context re-renders every consumer on every value change. Split contexts, memoize values, and know when you have outgrown it.

The Six TypeScript Utility Types I Use Every Week
TypeScript08 Oct 20202 min read

The Six TypeScript Utility Types I Use Every Week

Partial, Pick, Omit, Record, ReturnType, and Readonly - with the real-world scenario where each one earns its place.

Lazy Loading Images with Intersection Observer
Performance17 Sept 20202 min read

Lazy Loading Images with Intersection Observer

Scroll-listener lazy loading is obsolete. IntersectionObserver does it better in 15 lines, plus the new native loading=lazy attribute.

Code Splitting a React App: From 1.2MB to 280KB
Performance06 Aug 20202 min read

Code Splitting a React App: From 1.2MB to 280KB

Route-level React.lazy, vendor chunking, and bundle analysis - the exact steps that cut our initial bundle by 76%.

Debounce vs. Throttle: Pick the Right Tool
JavaScript28 Jul 20202 min read

Debounce vs. Throttle: Pick the Right Tool

Search inputs want debounce, scroll handlers want throttle, and both are ten lines of code. A practical guide with implementations.

Building Dashboard Layouts with CSS Grid Areas
CSS11 Jun 20202 min read

Building Dashboard Layouts with CSS Grid Areas

grid-template-areas turns dashboard layout from a div-nesting exercise into something you can read like ASCII art — and rearrange per breakpoint in one place.

Optional Chaining and Nullish Coalescing in Production Code
JavaScript21 May 20202 min read

Optional Chaining and Nullish Coalescing in Production Code

ES2020's ?. and ?? finally shipped in all major browsers. Where they shine, where they hide bugs, and how to configure Babel for older targets.

useEffect Cleanup Patterns You Actually Need
React09 Apr 20202 min read

useEffect Cleanup Patterns You Actually Need

Memory leaks from subscriptions and stale async calls are the most common hooks bug. Three cleanup patterns that fix 90% of them.

React vs. Angular
General23 Mar 202017 min read

React vs. Angular

React and AngularJS are both advanced, widely adopted JavaScript technologies for building interactive single-page applications. An in-depth comparison of componentization, data binding, performance, and more.

Prismic vs. WordPress
General18 Mar 20205 min read

Prismic vs. WordPress

Are you a WordPress developer? Wondering what makes prismic.io a more suitable CMS backend for you? Six reasons to consider the switch.

New JavaScript features for 2020
JavaScript18 Mar 20206 min read

New JavaScript features for 2020

In 2020 JavaScript got some exciting new features: Object.fromEntries, dynamic imports, String.matchAll, Promise.allSettled, and more.