DEV Community

Athreya aka Maneshwar
Athreya aka Maneshwar

Posted on

Avoiding the Extraneous Fetching Antipattern

Hi there! I'm Maneshwar. Right now, I’m building LiveAPI, a first-of-its-kind tool that helps you automatically index API endpoints across all your repositories. LiveAPI makes it easier to discover, understand, and interact with APIs in large infrastructures.


In modern web applications, performance often takes a hit not because of complex logic—but due to inefficient data access patterns.

One such pitfall is the Extraneous Fetching Antipattern: pulling in more data than necessary, leading to slower apps, wasted bandwidth, and increased processing load on both client and server.

Let’s walk through what this looks like in JavaScript (especially in Node.js / frontend apps), and how to avoid it.

What Is Extraneous Fetching?

This happens when your app fetches more data than it actually uses.

It often comes from trying to pre-load everything in advance or writing lazy queries like SELECT *.

Imagine needing a product’s name and price—but fetching full product details, reviews, and supplier info too.

Example 1: Fetching Everything, Then Filtering

Bad practice:

// Node.js + MongoDB const products = await db.collection('products').find().toArray(); const result = products.map(p => ({ id: p._id, name: p.name })); 
Enter fullscreen mode Exit fullscreen mode

Here, every document is loaded, even though only two fields are used.

Instead, fetch just what you need:

const result = await db .collection('products') .find({}, { projection: { _id: 1, name: 1 } }) .toArray(); 
Enter fullscreen mode Exit fullscreen mode

Example 2: Aggregating on the Client

Bad practice:

const orders = await db.collection('orders').find().toArray(); const total = orders.reduce((sum, o) => sum + o.totalAmount, 0); 
Enter fullscreen mode Exit fullscreen mode

The entire dataset comes over the wire—just to compute a sum.

Do it in the database:

const [result] = await db.collection('orders').aggregate([ { $group: { _id: null, total: { $sum: "$totalAmount" } } } ]).toArray(); const total = result?.total || 0; 
Enter fullscreen mode Exit fullscreen mode

Example 3: Filtering on the Client (accidental .toArray())

Bad practice:

const now = new Date(); const allProducts = await db.collection('products').find().toArray(); const oldProducts = allProducts.filter(p => p.createdAt < now); 
Enter fullscreen mode Exit fullscreen mode

This loads all documents, then filters.

Always push filtering to the DB:

const now = new Date(); const oldProducts = await db .collection('products') .find({ createdAt: { $lt: now } }) .toArray(); 
Enter fullscreen mode Exit fullscreen mode

Common Causes

  • Overusing .find() or ORM methods without proper filtering.
  • Calling .toArray() or converting streams early.
  • Fetching “just in case” instead of “just enough”.
  • Frontend APIs returning full objects instead of shaped, lean responses.

Best Practices

  • Be explicit: Always specify fields you need.
  • Use pagination: Avoid fetching unbounded lists.
  • Aggregate smartly: Push computation to DB where efficient.
  • Avoid SELECT *-style queries.
  • Be careful with .toArray() or .forEach() that pull in all data.
  • Frontend shaping: Use DTOs or serializers to strip unused fields before sending data.

Bonus: Paginating on Frontend

Avoid showing all data at once:

// Server app.get('/products', async (req, res) => { const page = Number(req.query.page) || 1; const pageSize = 20; const products = await db .collection('products') .find({}) .skip((page - 1) * pageSize) .limit(pageSize) .project({ name: 1, price: 1 }) .toArray(); res.json(products); }); 
Enter fullscreen mode Exit fullscreen mode

Final Thoughts

Not all processing belongs in the application layer. Fetch only what you need, where you need it.

Rely on your database for filtering, shaping, and aggregating—only if it’s good at it.

Overfetching may work during development, but in production, it kills performance.

Audit your data access patterns like you audit your code—look for what’s unnecessary and cut it out.


LiveAPI helps you get all your backend APIs documented in a few minutes.

With LiveAPI, you can generate interactive API docs that allow users to search and execute endpoints directly from the browser.

LiveAPI Demo

If you're tired of updating Swagger manually or syncing Postman collections, give it a shot.

Top comments (0)