Notes from the work.
Long-form insights and shorter blog posts on the problems I actually spend my weeks on — AI orchestration, platform modernization, delivery intelligence. Patterns, trade-offs, and the occasional strong opinion.
The hidden attribute is a suggestion — here's how to make it a rule
Your stylesheet can silently overrule the HTML hidden attribute — and the reason is cascade origin, not specificity. The classic one-line hardening fix, the until-found carve-out it needs now, and when the !important hammer is the wrong tool.
Two documents: the draft you review and the one you publish
A human-in-the-loop content pipeline needs two different documents: a short kernel for the decision, and the full piece for the reader. Conflating them fails both ways.
The filter that silently did nothing
A tag filter that looked finished and did absolutely nothing — no error, no effect. The cause was a one-line collision between the JavaScript and the CSS.
Keep credentials in data, not config
A deploy that might invalidate your API keys is a deploy you'll hesitate to run. That hesitation is a smell — and the cause is usually that secrets live in the wrong place.
Generate your sitemap from the database, not by hand
A hand-maintained sitemap.xml is drift waiting to happen. Generate it from the same database the site renders from, and it can't fall out of sync — because it is the content.
Your tests passed; the document is still broken
Every automated check passed and the document was still visibly broken. The only thing that caught it was rendering each page to an image and looking.
Compiling isn't proof: validate state-changing SQL against the real schema
'It compiled and the first batch ran fine' is the most expensive false comfort in data work.
The simplest design that ships beats the correct one that needs a committee
There's a version of architecture that optimizes only the diagram, and a version that also asks what the organization can actually approve. The second one ships more value, and it's the harder discipline.
Hardening a spec you didn't write
You're handed a build spec someone else wrote and asked to harden it. The temptation is to fix everything you see — which is exactly how you quietly make decisions that were never yours to make.
When the metric's meaning changes under you
The most dangerous performance fix in business intelligence is the one that also, quietly, changes what the numbers mean — because nobody is looking for that, and the dashboard doesn't announce it.
The generation token: verifying a dataset that races its own reload
A completeness check that runs for tens of minutes can collide with the next scheduled reload and report a false 'everything is missing.' An immutable token stamped at load time makes long verification safe.
Full reload beats the delta you can't trust
Incremental sync is the reflex. But it rests on a premise many source systems quietly fail to meet: that you can actually find out what changed — including what was deleted.
Your MCP server probably doesn't need its own deployment
The reflex when adding an MCP server to an existing product is to stand up a new service. Often the better answer is a route.
The silver layer is not a serving layer
A report that times out usually isn't a visuals problem - it's a grain problem.
Test the layers that pay: coverage is not a strategy
Asked to estimate 'adding unit tests' to a mature codebase, the honest answer is that the estimate is the wrong question.
Copilot Studio's sharp edges: scope claims and character budgets
Two constraints that cost real hours: the three-way OAuth scope mismatch behind most custom-connector 401s, and the hard 8,000-character ceiling on agent instructions.
Shipping a database transition while the site stays up
The zero-downtime rule for schema changes is one word: additive. The database transitions while the old code is still serving - and the two traps worth scars-first telling are the migration baseline and the default-value flip.
Your data has no opinions: the judgment layer AI reporting actually needs
An agent wired to your semantic model can answer 'what is the value?' perfectly and still be useless on 'is that good?' The missing piece isn't model quality - it's a judgment layer nobody's schema contains.
Grounding Copilot Studio on your docs: three places vector indexing silently fails
Pointing an agent at a vector index looks like configuration work. It is design work - and the defaults are wrong for documentation. Three failure modes that produce a finished-looking index and an agent that finds nothing.
Splitting a monolith without rewriting it: the API contract is the seam
You don't break up a monolith by choosing a new language. You break it up by finding the seam — and the seam is the API contract. A field guide to a split that ships in stages.
RLS-aware AI tools: securing enterprise data in Copilot Studio
An AI assistant that queries a governed dataset under a service identity is a data leak with good manners. Carrying row-level security all the way through — and why on-behalf-of is the whole game.
Orchestrating parallel agents without Durable Functions
Multi-agent systems don't need a heavyweight orchestration runtime to be reliable. What they need is routing, parallel execution, and a scoring discipline. The pattern, and where it ends.
Chained Azure Functions for resumable, high-volume API sync
A paginated API, a strict rate limit, and a job too big for one execution. Chained HTTP-triggered Functions give you a sync that resumes from any failure — without Durable Functions.
Have one of these problems right now?
The articles are the thinking. If you'd rather talk through the specific version of it on your desk, that's a faster conversation.