<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>Ameet Madan: Lessons</title><description>Short, applied lessons from building and shipping software.</description><link>https://ameetmadan.com/</link><item><title>Embrace Continuous Learning</title><link>https://ameetmadan.com/lessons/continuous-learning/</link><guid isPermaLink="true">https://ameetmadan.com/lessons/continuous-learning/</guid><description>The tech world evolves fast. Keeping up with trends, frameworks, and languages is key to staying relevant.</description></item><item><title>The library our auth system depended on was archived on GitHub two years ago. We found out during a compliance audit.</title><link>https://ameetmadan.com/lessons/audit-your-dependencies-on-a-schedule/</link><guid isPermaLink="true">https://ameetmadan.com/lessons/audit-your-dependencies-on-a-schedule/</guid><description>Dependency health should be checked on a schedule, especially for anything security sensitive. Nothing tells you a library went quiet.</description></item><item><title>Our on-call engineer muted the pager after 200 false alarms that month. Alarm 201 was the real outage.</title><link>https://ameetmadan.com/lessons/alert-fatigue-is-a-design-bug/</link><guid isPermaLink="true">https://ameetmadan.com/lessons/alert-fatigue-is-a-design-bug/</guid><description>An alert should mean exactly one thing. A human needs to act right now. Everything else belongs in a dashboard or digest.</description></item><item><title>I used to leave 15 comments on every pull request. Half were about semicolons. My team started dreading my reviews.</title><link>https://ameetmadan.com/lessons/automate-style-so-review-focuses-on-risk/</link><guid isPermaLink="true">https://ameetmadan.com/lessons/automate-style-so-review-focuses-on-risk/</guid><description>Automate style and formatting completely so human review time is reserved exclusively for logic, edge cases, and intent.</description></item><item><title>I&apos;ve read a hundred &apos;add login&apos; PRs from side projects. They all break the same way.</title><link>https://ameetmadan.com/lessons/auth-is-a-session-lifecycle/</link><guid isPermaLink="true">https://ameetmadan.com/lessons/auth-is-a-session-lifecycle/</guid><description>Auth isn&apos;t a login form, it&apos;s an identity and session lifecycle. Reset tokens, session invalidation, and rate limits included.</description></item><item><title>Our dashboard got slower the longer someone left it open. We assumed it was their laptop. It was every event listener we never cleaned up.</title><link>https://ameetmadan.com/lessons/clean-up-your-event-listeners/</link><guid isPermaLink="true">https://ameetmadan.com/lessons/clean-up-your-event-listeners/</guid><description>Every listener, subscription, or interval needs a matching teardown tied to the same lifecycle event that created it.</description></item><item><title>Our CPU was at 12%. Our database was idle. Every request still hung for 30 seconds. We weren&apos;t out of resources. We were out of connections.</title><link>https://ameetmadan.com/lessons/connection-pools-not-cpu/</link><guid isPermaLink="true">https://ameetmadan.com/lessons/connection-pools-not-cpu/</guid><description>Monitor connection pool checkout time and utilization as first class metrics. CPU and DB load can look fine while the pool is starved.</description></item><item><title>Our error rate dropped to zero overnight. We hadn&apos;t fixed anything. We&apos;d added a try/catch that swallowed every failure.</title><link>https://ameetmadan.com/lessons/dont-swallow-exceptions/</link><guid isPermaLink="true">https://ameetmadan.com/lessons/dont-swallow-exceptions/</guid><description>Never catch an exception without deciding what happens to that information. A quiet catch block deletes the only signal something is broken.</description></item><item><title>I explained event-driven architecture to our CEO using a food delivery app. It landed faster than my last three whiteboard diagrams combined.</title><link>https://ameetmadan.com/lessons/explain-architecture-with-analogies/</link><guid isPermaLink="true">https://ameetmadan.com/lessons/explain-architecture-with-analogies/</guid><description>Start with a system the listener already understands intuitively, introduce the benefit before the terminology, and only name the pattern last.</description></item><item><title>A feature flag stayed in the codebase two years after the feature fully shipped. Cleaning it up caused the outage.</title><link>https://ameetmadan.com/lessons/feature-flags-need-an-expiry-date/</link><guid isPermaLink="true">https://ameetmadan.com/lessons/feature-flags-need-an-expiry-date/</guid><description>Give every feature flag an owner and an expiry date at creation, or it becomes permanent untested config.</description></item><item><title>We added an index to fix one slow query. Every write got 3x slower for a year before anyone connected the two.</title><link>https://ameetmadan.com/lessons/indexes-have-a-write-cost/</link><guid isPermaLink="true">https://ameetmadan.com/lessons/indexes-have-a-write-cost/</guid><description>Before adding an index, check the table&apos;s read/write ratio and measure write latency, not just the query you were trying to fix.</description></item><item><title>We shipped an API key in our frontend bundle. It took nine months for someone to notice, and abuse it.</title><link>https://ameetmadan.com/lessons/never-ship-secrets-to-the-browser/</link><guid isPermaLink="true">https://ameetmadan.com/lessons/never-ship-secrets-to-the-browser/</guid><description>The security boundary is &quot;does this ever reach the browser,&quot; not &quot;is it in an env file.&quot; Client reachable code needs scoped, revocable keys or a backend proxy.</description></item><item><title>We asked AI to write a database migration. It passed every test. It would have silently dropped six months of customer data.</title><link>https://ameetmadan.com/lessons/review-ai-migrations-like-a-junior-pr/</link><guid isPermaLink="true">https://ameetmadan.com/lessons/review-ai-migrations-like-a-junior-pr/</guid><description>AI tools are confident about the code they can see and blind to what they can&apos;t. Grep the whole org for a column name before merging a migration, not just the service being changed.</description></item><item><title>I restructured our backend&apos;s folders exactly once. Three years and 20 engineers later, I still haven&apos;t touched it again.</title><link>https://ameetmadan.com/lessons/organize-code-by-domain-not-layer/</link><guid isPermaLink="true">https://ameetmadan.com/lessons/organize-code-by-domain-not-layer/</guid><description>Organize by domain/feature first and technical layer second. A folder should map to an owner, not a technical concern.</description></item><item><title>Two engineers argued for twenty minutes about a variable name. The unhandled null case three lines down shipped anyway.</title><link>https://ameetmadan.com/lessons/review-for-risk-not-taste/</link><guid isPermaLink="true">https://ameetmadan.com/lessons/review-for-risk-not-taste/</guid><description>Review against whether a bug fails loudly, whether someone else can safely change it later, and whether it&apos;s easy to reason about, not naming taste.</description></item><item><title>A user signed up with an emoji in their name. Nothing broke for eight months. Then our export job started crashing every night at 3am.</title><link>https://ameetmadan.com/lessons/utf8-is-not-optional/</link><guid isPermaLink="true">https://ameetmadan.com/lessons/utf8-is-not-optional/</guid><description>Use full UTF 8 end to end and test with emoji and non ASCII strings as normal QA. Bad encoding can sit silently for months before it surfaces.</description></item></channel></rss>