<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Aditya Kushwah</title>
    <description>The latest articles on DEV Community by Aditya Kushwah (@aditya_kushwah).</description>
    <link>https://dev.to/aditya_kushwah</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3840854%2F006d6e21-8749-42f8-ae5e-abea53338cb1.jpg</url>
      <title>DEV Community: Aditya Kushwah</title>
      <link>https://dev.to/aditya_kushwah</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aditya_kushwah"/>
    <language>en</language>
    <item>
      <title>Your Codebase Knows More Than Your Team Does</title>
      <dc:creator>Aditya Kushwah</dc:creator>
      <pubDate>Wed, 01 Apr 2026 04:09:43 +0000</pubDate>
      <link>https://dev.to/aditya_kushwah/your-codebase-knows-more-than-your-team-does-421p</link>
      <guid>https://dev.to/aditya_kushwah/your-codebase-knows-more-than-your-team-does-421p</guid>
      <description>&lt;p&gt;Developer A builds the dashboard. Queries the users table.&lt;/p&gt;

&lt;p&gt;Developer B builds settings. Queries the users table.&lt;/p&gt;

&lt;p&gt;Developer C builds checkout. Queries the users table.&lt;/p&gt;

&lt;p&gt;Each developer knows their part. Nobody knows all three hit the same table on every page load.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Three files. Three developers. Three code reviews. One table getting hammered, and nobody can see it.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This isn't a skill problem. These are good developers writing good code. Each file passes code review. Each endpoint returns 200.&lt;/p&gt;

&lt;p&gt;The problem isn't in any file. It's in the space between files. The connections that exist at runtime but are invisible in code.&lt;/p&gt;




&lt;h2&gt;
  
  
  The gap that compounds every sprint
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;th&gt;Endpoints&lt;/th&gt;
&lt;th&gt;Developers&lt;/th&gt;
&lt;th&gt;System understanding&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Month 1&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Full&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Month 3&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;~80%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Month 6&lt;/td&gt;
&lt;td&gt;60&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;~50%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Month 12&lt;/td&gt;
&lt;td&gt;120+ AI generated&lt;/td&gt;
&lt;td&gt;4+&lt;/td&gt;
&lt;td&gt;Maybe 30%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Every sprint adds endpoints. No sprint adds understanding.&lt;/p&gt;

&lt;p&gt;Architecture diagrams go stale the week they're drawn. Knowledge-sharing meetings cover what people remember, not what they've forgotten. The gap between what the codebase does and what the team knows grows silently, sprint after sprint. Then something breaks and everyone discovers the complexity that was always there.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This isn't a failure of process. No amount of documentation fixes it. The codebase grows structurally. Understanding doesn't.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What lives in the gaps
&lt;/h2&gt;

&lt;p&gt;These are patterns that exist in real codebases right now. Not bugs. Not failing tests. Just waste and risk that nobody knows about.&lt;/p&gt;

&lt;h3&gt;
  
  
  The same query, four times
&lt;/h3&gt;

&lt;p&gt;A &lt;code&gt;SELECT * FROM users WHERE id = $1&lt;/code&gt; runs on every page load. The nav bar fetches it. The dashboard fetches it. The notification badge fetches it. The activity feed fetches it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Four endpoints. Four round trips. Same row every time.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Two teams, same external API, no idea
&lt;/h3&gt;

&lt;p&gt;The pricing page fetches exchange rates from a third-party service. So does checkout. Built independently, months apart, by different people. Separate error handling. Separate caching. Double the rate limit exposure.&lt;/p&gt;

&lt;h3&gt;
  
  
  The silent regression
&lt;/h3&gt;

&lt;p&gt;An endpoint that responded in 120ms three sprints ago now takes 900ms. A refactor added an eager-load. Tests still pass. Response is still correct. Nobody tracks endpoint performance across sprints. They track whether the code works, not how it performs.&lt;/p&gt;

&lt;h3&gt;
  
  
  The accidental fan-out
&lt;/h3&gt;

&lt;p&gt;A single page load triggers three component mounts. Each one fetches &lt;code&gt;/api/user/me&lt;/code&gt; on its own. Three identical queries. Three identical serializations. Three times the load. For one page view.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;None of these show up in error logs. None fail tests. None get caught in code review. All of them are real.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Code review sees files. Nobody sees the system.
&lt;/h2&gt;

&lt;p&gt;Pull up any PR on your project right now.&lt;/p&gt;

&lt;p&gt;The reviewer reads the diff. Variable names look good. Logic is correct. Tests pass. Approved.&lt;/p&gt;

&lt;p&gt;But the reviewer doesn't know that the query in this PR already runs from three other routes. They don't know the external API call duplicates one in another service. They can't know. The PR shows one file. It doesn't show the rest of the system.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Code review is file-shaped. Systems are graph-shaped.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's the fundamental limit of file-based review in a system-level world. The tool shows exactly what changed. It can't show what that change means in the context of everything else that's already running.&lt;/p&gt;




&lt;h2&gt;
  
  
  AI makes the gap wider, not narrower
&lt;/h2&gt;

&lt;p&gt;This is the part nobody talks about.&lt;/p&gt;

&lt;p&gt;AI coding tools write correct code fast. Ask your AI assistant to build a settings page. It generates clean endpoints, proper validation, solid error handling. The code works. It passes review.&lt;/p&gt;

&lt;p&gt;But it wrote each endpoint in isolation. It didn't check whether those endpoints duplicate queries that already run from three other routes. It can't. It has file context. It doesn't have runtime context.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;AI reads your codebase. It doesn't see your system.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The faster AI writes code, the faster the codebase outgrows the team's understanding. Every generated endpoint is another node in a system graph nobody is looking at. Code quality goes up. System awareness goes down.&lt;/p&gt;

&lt;p&gt;We're accelerating the exact problem that was already compounding. More code, faster, with less understanding of how it all connects.&lt;/p&gt;




&lt;h2&gt;
  
  
  Your codebase already knows all of this
&lt;/h2&gt;

&lt;p&gt;Here's the thing. Your application already has this information. Every request that hits your server triggers a chain of queries, fetches, logs, and responses. The runtime knows which tables get hit together, which services depend on each other, which endpoints share data sources.&lt;/p&gt;

&lt;p&gt;It just doesn't tell anyone.&lt;/p&gt;

&lt;p&gt;The knowledge exists. It lives in the execution path of every request. But it disappears the moment the response is sent. No record. No correlation. No visibility.&lt;/p&gt;

&lt;p&gt;What if it didn't disappear?&lt;/p&gt;




&lt;h2&gt;
  
  
  Seeing the system
&lt;/h2&gt;

&lt;p&gt;We built &lt;a href="https://brakit.ai" rel="noopener noreferrer"&gt;Brakit&lt;/a&gt; to close this gap. One import. Zero config. &lt;a href="https://brakit.ai/docs/introduction" rel="noopener noreferrer"&gt;Get started here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Start your app the way you always do. Open &lt;code&gt;/__brakit&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  See what a single request actually does
&lt;/h3&gt;

&lt;p&gt;Not just the handler. Everything behind it. Every query, every outgoing fetch, every log, all on one timeline:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0n3jusl2kg2fcnwlnhx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0n3jusl2kg2fcnwlnhx.png" alt=" " width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;47 queries for one checkout. Invisible in the code. Obvious in the timeline.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  See patterns across your whole application
&lt;/h3&gt;

&lt;p&gt;The same query appearing from four different routes. The same external API called by two unrelated endpoints. The same table hit on every page load. Not found by searching. Found by watching the system run.&lt;/p&gt;

&lt;h3&gt;
  
  
  See the graph
&lt;/h3&gt;

&lt;p&gt;Every endpoint, every table, every external service, and how they actually connect at runtime:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft5jwcy5d6od1f3dggec9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft5jwcy5d6od1f3dggec9.png" alt=" " width="800" height="335"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not a diagram someone drew. A live map built from real requests. Your actual architecture, as it exists right now.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automatic detection
&lt;/h3&gt;

&lt;p&gt;Brakit doesn't just show you data. It analyzes patterns across requests:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What it catches&lt;/th&gt;
&lt;th&gt;How&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;N+1 queries&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Same query shape fired 5+ times in a single request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Duplicate calls&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Same endpoint hit multiple times per page load&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Security findings&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Passwords in responses, tokens in URLs, stack traces leaking, PII exposure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Performance regression&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;p95 latency tracked across sessions, regressions flagged automatically&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These aren't manual investigations. They surface on their own, from live traffic, as you develop.&lt;/p&gt;




&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;Brakit runs inside your Node.js process. It hooks into the HTTP layer, &lt;code&gt;fetch&lt;/code&gt;, &lt;code&gt;console&lt;/code&gt;, and your database client (Prisma, pg, or mysql2) automatically.&lt;/p&gt;

&lt;p&gt;Every incoming request gets a unique ID. Every query, fetch, and log that happens during that request is correlated back to it through async context. That's how a single request timeline can show you 47 queries you didn't know existed. That's how the graph knows which endpoints hit which tables.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Brakit never runs in production. It checks &lt;code&gt;NODE_ENV&lt;/code&gt;, detects CI environments, and disables itself. It never throws errors into your application. Every hook is wrapped in safety layers. If anything goes wrong, it fails silently and your app continues untouched.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It works with Express, Fastify, Koa, or raw &lt;code&gt;http.createServer&lt;/code&gt;. No agents to install. No environment variables. No dashboard to configure. One import.&lt;/p&gt;




&lt;h2&gt;
  
  
  One more thing
&lt;/h2&gt;

&lt;p&gt;Brakit exposes its findings through MCP, the Model Context Protocol. That means AI assistants like Claude and Cursor can query your running application's runtime data directly.&lt;/p&gt;

&lt;p&gt;Your AI assistant can already read your files. Now it can see your system. It can look at open issues, inspect endpoint performance, verify whether a fix actually worked. All from live telemetry, not static code.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;This is the piece that starts to close the AI gap.&lt;/strong&gt; Give the AI the same system-level context that developers are missing, and it stops generating endpoints in isolation.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The real problem
&lt;/h2&gt;

&lt;p&gt;Your codebase isn't broken. Your understanding of it is incomplete. And it gets more incomplete every sprint.&lt;/p&gt;

&lt;p&gt;The fix isn't writing better code. Your code is fine. The fix is seeing the code you already have as a connected system. The queries, the dependencies, the patterns, the waste. All of it visible, all of it correlated, all of it automatic.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Your codebase has always known more than your team. Brakit just makes that knowledge visible.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's open source, runs locally, and your data never leaves your machine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://brakit.ai/docs/introduction" rel="noopener noreferrer"&gt;Get started →&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>database</category>
      <category>architecture</category>
    </item>
    <item>
      <title>The LiteLLM Attack and What It Means for Every Dev Tool</title>
      <dc:creator>Aditya Kushwah</dc:creator>
      <pubDate>Wed, 25 Mar 2026 19:57:05 +0000</pubDate>
      <link>https://dev.to/aditya_kushwah/the-litellm-attack-and-what-it-means-for-every-dev-tool-ojm</link>
      <guid>https://dev.to/aditya_kushwah/the-litellm-attack-and-what-it-means-for-every-dev-tool-ojm</guid>
      <description>&lt;p&gt;Yesterday, two versions of LiteLLM, a Python library used by thousands of AI applications to route LLM requests, were published to PyPI with credential-stealing malware baked in. The malicious code harvested SSH keys, cloud credentials, database passwords, Kubernetes secrets, and crypto wallets from every machine that installed the package.&lt;/p&gt;

&lt;p&gt;The library gets over 3 million downloads per day. The compromised versions were live for about 3 hours before PyPI pulled them.&lt;/p&gt;

&lt;p&gt;Every dev tool that runs inside your application has the exact same risk profile. Here are some learnings for every dev tool builder.&lt;/p&gt;




&lt;h2&gt;
  
  
  What happened
&lt;/h2&gt;

&lt;p&gt;Here's the short version. A threat group called TeamPCP had been compromising open source security tools for the past week. They started with Aqua Security's Trivy vulnerability scanner on March 19, then Checkmarx's KICS scanner on March 23. LiteLLM used Trivy in its CI/CD pipeline. When Trivy was compromised, it leaked LiteLLM's PyPI publishing token. The attackers used that token to publish two malicious versions, 1.82.7 and 1.82.8.&lt;/p&gt;

&lt;p&gt;The clever part: version 1.82.8 used Python's &lt;code&gt;.pth&lt;/code&gt; mechanism, a configuration file that executes code every time the Python interpreter starts. You didn't even need to import LiteLLM. Simply having it installed was enough to trigger the malware.&lt;/p&gt;

&lt;p&gt;The malware collected everything it could find. Environment variables, SSH keys, AWS/GCP/Azure credentials, database configs, API keys, crypto wallets. It encrypted it all with a 4096-bit RSA key and sent it to an attacker-controlled domain that looked like legitimate LiteLLM infrastructure.&lt;/p&gt;

&lt;p&gt;The LiteLLM maintainer had 2FA enabled. It didn't matter. The attack came through a compromised dependency in the CI/CD pipeline, not through the maintainer's account directly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why dev tools are high-value targets
&lt;/h2&gt;

&lt;p&gt;LiteLLM isn't just a library. It's an AI gateway. It sits between applications and LLM providers, routing API calls. That position gives it access to API keys for every LLM provider the application uses.&lt;/p&gt;

&lt;p&gt;This is why dev tools are attractive targets. Developers trust them implicitly. They often run with elevated access. And a single compromised version reaches thousands of machines before anyone notices.&lt;/p&gt;

&lt;p&gt;The pattern is the same across all of these tools:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trivy&lt;/strong&gt; is a security scanner. Ironic. The tool meant to find vulnerabilities became the vulnerability. It had access to CI/CD secrets because that's where security scanners run.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LiteLLM&lt;/strong&gt; is an LLM router. It had access to every LLM API key because that's its job.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dev tools that run inside your app&lt;/strong&gt; have access to everything the app has access to. Database connections, auth tokens, environment variables, request bodies. That's what makes them useful. It's also what makes a compromised version devastating.&lt;/p&gt;




&lt;h2&gt;
  
  
  What every dev tool should be doing
&lt;/h2&gt;

&lt;p&gt;Any dev tool that runs inside your application, whether it's an observability tool, an error tracker, an analytics SDK, or an instrumentation library, has access to everything your app has access to. Database connections, auth tokens, environment variables, request bodies. That's what makes these tools useful. It's also what makes a compromised version devastating.&lt;/p&gt;

&lt;p&gt;The question isn't whether the risk exists. It's what the maintainers are doing about it. Here's what every dev tool should be doing:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Minimal dependencies.&lt;/strong&gt; Every dependency is an attack surface. LiteLLM was compromised through Trivy, a transitive dependency in its build pipeline. The fewer dependencies you ship, the smaller your attack surface.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2FA on package registries.&lt;/strong&gt; npm and PyPI both support two-factor authentication. This protects against direct account compromise but as LiteLLM showed, it doesn't protect against token theft from CI/CD. It's a baseline, not a solution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open source.&lt;/strong&gt; Every line of code should be auditable. A malicious addition to a closed-source SDK could go unnoticed for months. Open source makes it visible in the diff.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Local-first architecture.&lt;/strong&gt; If your tool doesn't need a cloud server, don't have one. No cloud means no infrastructure for an attacker to impersonate. The LiteLLM malware exfiltrated data to &lt;code&gt;models.litellm.cloud&lt;/code&gt;, a domain that looked official but wasn't. Tools that make no outbound connections eliminate this vector entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No static publish tokens.&lt;/strong&gt; Use trusted publishing with OIDC instead of long-lived tokens. Tie package publishing to specific CI workflows via short-lived tokens. There should be no NPM_TOKEN or PYPI_TOKEN sitting in a CI/CD secret that can be stolen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pinned CI/CD dependencies.&lt;/strong&gt; Pin every GitHub Action to a specific commit SHA, not a version tag. This is exactly how the Trivy attack propagated. The attackers rewrote version tags to point to malicious code. Pinning to commit hashes prevents this.&lt;/p&gt;




&lt;h2&gt;
  
  
  What you should check in your own projects
&lt;/h2&gt;

&lt;p&gt;This isn't just about LiteLLM. Every project with third-party dependencies carries supply chain risk. Here's what you can do:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Audit your dev dependencies.&lt;/strong&gt; Run &lt;code&gt;npm ls&lt;/code&gt; or &lt;code&gt;pip list&lt;/code&gt; and look at what's installed. Do you know what every package does? Do you know who maintains it? Dev dependencies are often treated as lower risk, but they run on your machine with the same permissions as production dependencies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pin GitHub Actions to commit SHAs.&lt;/strong&gt; If your CI/CD workflow uses &lt;code&gt;actions/checkout@v4&lt;/code&gt;, change it to &lt;code&gt;actions/checkout@&amp;lt;specific-sha&amp;gt;&lt;/code&gt;. Tags can be rewritten. Commits can't. This is the single most impactful change you can make today.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Review lockfile changes.&lt;/strong&gt; When &lt;code&gt;package-lock.json&lt;/code&gt; or &lt;code&gt;yarn.lock&lt;/code&gt; changes in a PR, actually look at what changed. A new transitive dependency or an unexpected version bump is worth investigating.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check if your tools read .env files.&lt;/strong&gt; Many dev tools read environment files to auto-configure. That's convenient, but it also means they have access to your secrets. Know which tools read your &lt;code&gt;.env&lt;/code&gt; and what they do with the data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use &lt;code&gt;npm audit signatures&lt;/code&gt;.&lt;/strong&gt; This verifies that published packages have valid provenance, meaning they were built from a known source repository through a verified CI/CD pipeline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep dev tools in devDependencies.&lt;/strong&gt; If a tool is only for development, make sure it's in &lt;code&gt;devDependencies&lt;/code&gt;, not &lt;code&gt;dependencies&lt;/code&gt;. Most production build pipelines strip devDependencies, which means the tool won't be present in your deployed application. This doesn't prevent attacks on your development machine, but it limits the blast radius.&lt;/p&gt;




&lt;h2&gt;
  
  
  The uncomfortable truth
&lt;/h2&gt;

&lt;p&gt;There's no way to make supply chain attacks impossible. LiteLLM's maintainer did things right. 2FA was enabled, the project was well-maintained, the code was open source. The attack came through a dependency of a dependency in the build pipeline. No amount of vigilance on the maintainer's part would have caught it before it happened.&lt;/p&gt;

&lt;p&gt;The open source ecosystem is built on trust. When you run &lt;code&gt;npm install&lt;/code&gt;, you're trusting the maintainer, their CI/CD pipeline, every dependency in their build, every GitHub Action they use, and the package registry itself. That chain of trust is long, and every link is a potential point of compromise.&lt;/p&gt;

&lt;p&gt;What we can do is add layers of defense. No single measure prevents all attacks. But 2FA plus minimal dependencies plus pinned CI/CD plus trusted publishing plus open source plus local-first architecture makes each successive attack harder to execute and easier to detect.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Links:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/BerriAI/litellm/issues/24512" rel="noopener noreferrer"&gt;LiteLLM GitHub issue #24512&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/brakit-ai/brakit" rel="noopener noreferrer"&gt;Brakit on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>security</category>
      <category>opensource</category>
      <category>ai</category>
      <category>llm</category>
    </item>
    <item>
      <title>Your Next.js App Makes the Same Database Query 5 Times Per Page Load</title>
      <dc:creator>Aditya Kushwah</dc:creator>
      <pubDate>Mon, 23 Mar 2026 23:17:30 +0000</pubDate>
      <link>https://dev.to/aditya_kushwah/your-nextjs-app-makes-the-same-database-query-5-times-per-page-load-3j24</link>
      <guid>https://dev.to/aditya_kushwah/your-nextjs-app-makes-the-same-database-query-5-times-per-page-load-3j24</guid>
      <description>&lt;p&gt;Open your Next.js app. Navigate to any page with a few components. Now count how many times &lt;code&gt;SELECT * FROM users WHERE id = ?&lt;/code&gt; runs.&lt;/p&gt;

&lt;p&gt;You probably don't know. Nobody does. Because every request returns 200, every component renders correctly, and your app "works."&lt;/p&gt;

&lt;p&gt;But behind that working page, the same query might be running &lt;strong&gt;5 times&lt;/strong&gt;. Once for the navbar. Once for the sidebar. Once for the main content. Once for the settings panel. And once more because React Strict Mode ran your effect twice.&lt;/p&gt;

&lt;p&gt;That's 5 identical round trips to your database for data that hasn't changed in the last 200 milliseconds.&lt;/p&gt;




&lt;h2&gt;
  
  
  This isn't hypothetical
&lt;/h2&gt;

&lt;p&gt;Here's a typical Next.js API route:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/api/user/route.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findUnique&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple. Clean. Ships code review.&lt;/p&gt;

&lt;p&gt;Now here's the problem. This endpoint gets called from:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Why it fetches &lt;code&gt;/api/user&lt;/code&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Layout navbar&lt;/td&gt;
&lt;td&gt;Show the user's name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dashboard page&lt;/td&gt;
&lt;td&gt;Display user stats&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Settings page&lt;/td&gt;
&lt;td&gt;Pre-fill the form&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Profile sidebar&lt;/td&gt;
&lt;td&gt;Show the avatar&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Notification bell&lt;/td&gt;
&lt;td&gt;Check preferences&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each component independently calls &lt;code&gt;fetch('/api/user')&lt;/code&gt;. Each call hits the API route. Each route runs &lt;code&gt;prisma.user.findUnique()&lt;/code&gt;. Each query goes to PostgreSQL and comes back.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Five components. Five requests. Five queries. One user record.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Why this happens
&lt;/h2&gt;

&lt;p&gt;It's not bad code. It's the natural result of component-based architecture.&lt;/p&gt;

&lt;p&gt;In React and Next.js, components are self-contained. A &lt;code&gt;&amp;lt;UserAvatar&amp;gt;&lt;/code&gt; fetches its own data. A &lt;code&gt;&amp;lt;PermissionGate&amp;gt;&lt;/code&gt; checks permissions independently. This is &lt;em&gt;good&lt;/em&gt; software design.&lt;/p&gt;

&lt;p&gt;But it means every component that needs user data makes its own request. And nobody sees the duplication because:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DevTools shows a flat list.&lt;/strong&gt;&lt;br&gt;
You see 5 requests to &lt;code&gt;/api/user&lt;/code&gt;, but they're mixed in with 20 other requests. You'd have to manually notice they're all the same.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Each request succeeds.&lt;/strong&gt;&lt;br&gt;
200 OK, correct data, fast enough. No error to catch. No warning to trigger.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Different developers wrote different components.&lt;/strong&gt;&lt;br&gt;
Developer A built the navbar. Developer B built the sidebar. Neither knows the other fetches &lt;code&gt;/api/user&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code review doesn't catch it.&lt;/strong&gt;&lt;br&gt;
Each component's code is correct in isolation. The duplication only exists at runtime, when all components render on the same page.&lt;/p&gt;


&lt;h2&gt;
  
  
  The real cost
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;"So what? Queries are fast."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let's do the math:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Duplicate queries per page load&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Time per query (warm database)&lt;/td&gt;
&lt;td&gt;30ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Daily active users&lt;/td&gt;
&lt;td&gt;1,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Page loads per session&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Unnecessary queries per day&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;50,000&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Wasted latency per page&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;150ms&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And if your database is under load, those "fast" 30ms queries start taking 200ms. Suddenly your app feels sluggish for no obvious reason.&lt;/p&gt;

&lt;p&gt;Each duplicate also means an extra HTTP request, an extra API route invocation, an extra connection from the pool, and extra memory allocation. All for data you already have.&lt;/p&gt;


&lt;h2&gt;
  
  
  React Strict Mode makes it worse
&lt;/h2&gt;

&lt;p&gt;React Strict Mode (enabled by default in Next.js) runs every &lt;code&gt;useEffect&lt;/code&gt; twice in development. Every &lt;code&gt;fetch()&lt;/code&gt; in an effect fires twice.&lt;/p&gt;

&lt;p&gt;Your 5 duplicate requests become &lt;strong&gt;10&lt;/strong&gt;. Your 5 database queries become &lt;strong&gt;10&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The confusing part: you see 10 requests to &lt;code&gt;/api/user&lt;/code&gt; and think &lt;em&gt;"my app is broken."&lt;/em&gt; But 5 are Strict Mode ghosts that don't happen in production. And the other 5 are real duplicates. You can't tell which is which from DevTools.&lt;/p&gt;


&lt;h2&gt;
  
  
  The solutions everyone recommends
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"Use React Query / SWR"&lt;/strong&gt; — Deduplicates on the client side. Works well, but requires refactoring every component to use the same query key. Doesn't help with Server Components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Lift the fetch to a parent"&lt;/strong&gt; — Pass data down as props. Works, but breaks component encapsulation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Use a shared layout loader"&lt;/strong&gt; — Fetch in &lt;code&gt;layout.tsx&lt;/code&gt;, share via Context. Good pattern, but requires architectural planning upfront.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Add caching"&lt;/strong&gt; — Redis? In-memory? What TTL? Now you have cache invalidation problems.&lt;/p&gt;

&lt;p&gt;All valid. But they all require you to &lt;strong&gt;already know which queries are duplicated.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's the hard part. You can't fix what you can't see.&lt;/p&gt;


&lt;h2&gt;
  
  
  Seeing the problem
&lt;/h2&gt;

&lt;p&gt;This is where observability at the API level becomes critical. Not application-level logging (too verbose). Not infrastructure monitoring (too high-level). You need to see your API as a connected system — which endpoints are called together, which queries they share, and how they relate to what the user actually did.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://brakit.ai" rel="noopener noreferrer"&gt;Brakit&lt;/a&gt; is an open-source dev tool that does exactly this. You add one line to your Next.js app, and it captures every HTTP request, database query, and external fetch — grouped by user action.&lt;/p&gt;

&lt;p&gt;Instead of a flat list of 10 requests in DevTools, you see everything nested, timed, and connected:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7qjl8go9vq5159vr74tm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7qjl8go9vq5159vr74tm.png" alt="Brakit dashboard showing nested requests and queries grouped by user action" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Duplicates are flagged automatically. &lt;code&gt;SELECT users&lt;/code&gt; running across multiple endpoints is highlighted. And React Strict Mode duplicates are marked separately — &lt;em&gt;"React Strict Mode duplicate — does not happen in production"&lt;/em&gt; — so you know which to fix and which to ignore.&lt;/p&gt;


&lt;h2&gt;
  
  
  What to do about it
&lt;/h2&gt;

&lt;p&gt;Once you can see the duplication, the fixes are straightforward:&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Deduplicate at the request level
&lt;/h3&gt;

&lt;p&gt;Use React Query or SWR so multiple components share one request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// hooks/useUser.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;queryFn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
    &lt;span class="na"&gt;staleTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every component that calls &lt;code&gt;useUser()&lt;/code&gt; shares the same request and cache.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Deduplicate at the query level
&lt;/h3&gt;

&lt;p&gt;Extract shared queries to a data access layer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lib/data/user.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findUnique&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;React's &lt;code&gt;cache()&lt;/code&gt; deduplicates within a single server render. For cross-request caching, use &lt;code&gt;unstable_cache&lt;/code&gt; or a dedicated cache layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Move shared data to layouts
&lt;/h3&gt;

&lt;p&gt;Fetch once, share via context:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/layout.tsx&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UserProvider&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/UserProvider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The broader pattern
&lt;/h2&gt;

&lt;p&gt;Duplicate queries are the most common backend performance issue in component-based architectures. They're invisible in code review, undetectable in unit tests, and only manifest at runtime when real components compose on real pages.&lt;/p&gt;

&lt;p&gt;The fix isn't complicated. The hard part is seeing the problem.&lt;/p&gt;

&lt;p&gt;If you want to see what your Next.js app actually does behind every page load — which queries run, which are duplicated, and which components are responsible — try &lt;a href="https://brakit.ai" rel="noopener noreferrer"&gt;Brakit&lt;/a&gt;. One command, zero config, and your duplicate queries become impossible to miss.&lt;/p&gt;

&lt;p&gt;It's open source, runs locally, and does nothing in production. Your data never leaves your machine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://brakit.ai/docs/introduction" rel="noopener noreferrer"&gt;Get started in 2 minutes →&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>database</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
