🚀 Executive Summary

TL;DR: Modern applications like Notion often suffer from embarrassing slowness due to underlying architectural issues such as Electron-based builds, monolithic frontends, and excessive data fetching. Solutions range from user-side mitigations like using web versions and ad-blockers, to engineering-led architectural overhauls involving aggressive caching, smarter APIs, and frontend code-splitting, or even a strategic rebuild or migration.

🎯 Key Takeaways

  • Electron-based applications inherently consume significant memory and CPU by bundling an entire Chromium browser instance for each app.
  • Performance bottlenecks are often caused by monolithic JavaScript bundles requiring clients to download and parse megabytes of unused code, and chatty APIs that over-fetch data.
  • Effective solutions include user-side mitigation (e.g., network-level ad-blockers, app restarts), architectural changes (CDN, GraphQL/REST query parameters, code-splitting), and, as a last resort, a strategic rebuild or migration.

Isn’t Notion embarrassed of the app?

Summary: A Senior DevOps Engineer breaks down why modern apps like Notion can feel embarrassingly slow, using a real-world “war story” to explain the root causes and provide three actionable solutions—from quick user-side hacks to architectural overhauls.

Why Your ‘Simple’ App Feels Like a Forklift in a Phone Booth (And How to Fix It)

I remember a launch. It was supposed to be a simple internal dashboard for the sales team—a few charts, a table, nothing crazy. By 10 AM on Monday, my pager was screaming. Our primary read replica, prod-db-replica-01, was pinned at 100% CPU, and the whole company’s reporting was grinding to a halt. The culprit? That “simple” dashboard was fetching the entire multi-gigabyte customer table and doing the filtering in the browser on every single page load. For every single user. Reading a recent Reddit thread titled “Isn’t Notion embarrassed of the app?” brought that memory roaring back. It’s the perfect example of how a series of seemingly small architectural trade-offs can create a product that feels slow, bloated, and fundamentally broken to the end-user. It’s death by a thousand papercuts.

The “Why”: It’s Not Magic, It’s Monoliths and Megabytes

So, you’re looking at an app like Notion, and you’re wondering, “How can a text editor use a gigabyte of RAM?” Look, I get the frustration. The root cause isn’t usually one single thing, but a cocktail of common development practices that prioritize shipping features over performance. Here’s what’s likely happening under the hood:

  • The Electron Problem: Many modern desktop apps (Slack, VS Code, Notion) are built with Electron. This means they are essentially a bundled version of the Chromium browser running a web app. You’re not just running the app; you’re running an entire browser just for that app. It’s a great way to build cross-platform quickly, but it comes at a steep cost in memory and CPU.
  • Monolithic Frontends: In the rush to build, teams often bundle all the JavaScript for the entire application into one or two massive files. Your browser has to download, parse, and execute megabytes of code just to render the login screen, even if you never use 90% of those features.
  • Chatty APIs & Over-fetching: Just like my war story, many apps fetch way more data than they need. The API might send a 5MB JSON object with every piece of data you’ve ever created, when all the app needed was the title of your last five pages. This clogs the network and forces the app to do heavy lifting on your machine.

Now that we’ve diagnosed the patient, let’s talk treatment. I’ve got three levels of fixes, from a band-aid to major surgery.

Solution 1: The Quick Fix (Taming the Beast on Your Machine)

This is for the user or the junior dev who has no control over the backend. You can’t fix their architecture, but you can mitigate the damage on your own system. It’s hacky, but it often works.

First, if there’s a web version, use it. It runs in a browser tab you can close, isolating its resource hunger from your desktop. Second, check your own machine. What does htop or Task Manager tell you? You might see something like this:


  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
15701 dvance    20   0   2.58g   1.2g   101m S  88.5   8.1   1:35.18 BloatedApp
 4590 dvance    20   0   1.89g   512m    89m S  45.0   3.2   0:55.12 BloatedApp --renderer
 4601 dvance    20   0   1.21g   256m    65m S  22.1   1.6   0:23.45 BloatedApp --gpu-process

Seeing that? That’s the app eating your resources for breakfast. The most effective “quick fix” is often aggressive filtering. Use a network-level ad-blocker (like Pi-hole or uBlock Origin) and configure it to block not just ads, but the dozens of analytics, tracking, and session replay scripts that many apps load. Each one adds overhead. Cutting them out can dramatically improve responsiveness.

Pro Tip: Don’t underestimate the power of simply restarting the app. Electron apps, in particular, can suffer from memory leaks over long sessions. A quick restart can often bring an unruly app back in line, at least temporarily.

Solution 2: The Permanent Fix (Architecting for Sanity)

Alright, now we’re putting on our Architect hats. This is for the engineering team that owns the app. You need to stop the bleeding at the source. This involves changing how you build and serve your application.

1. Aggressive Caching & CDN: Your static assets (JS, CSS, images) should be served from a Content Delivery Network (CDN) like Cloudflare or AWS CloudFront, with long cache lifetimes. This offloads traffic from your origin servers and gets content to users faster. Here’s a conceptual Nginx config snippet to enforce browser caching:


location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
    expires 1y;
    add_header Pragma public;
    add_header Cache-Control "public";
}

2. Smarter APIs: Stop over-fetching. Implement GraphQL or use query parameters in your REST APIs to allow the client to request only the data it needs. Instead of one giant /get-all-user-data endpoint, create smaller, targeted endpoints like /get-page-titles or /get-page-content?id=123. Use a caching layer like Redis or Memcached in front of your database for frequently requested, non-critical data.

3. Frontend Build Optimizations: Work with your frontend team to implement code-splitting in your build pipeline (Webpack, Vite, etc.). This breaks up your monolithic JavaScript bundle into smaller chunks that are loaded on demand. The user only downloads the code for the feature they are currently using, drastically cutting initial load times.

Solution 3: The ‘Nuclear’ Option (It’s Not Me, It’s You)

Sometimes, the technical debt is too high. The architecture is fundamentally flawed, and incremental fixes are just costly, temporary patches. This is the hardest solution to accept, but often the most necessary. You have to evaluate whether to rebuild or migrate.

This is a business decision disguised as a technical one. You need to make a case using data: user-reported performance tickets, server hosting costs, developer hours spent on performance whack-a-mole versus building new features. Present a clear-eyed comparison of the options.

Option Effort Impact Risk
Maintain (Solution 2) Medium-High (Ongoing) Medium (Incremental) Low (Can be done piece by piece)
Rebuild (In-house) Very High Very High High (Could fail or take too long)
Migrate (To a better tool) High Very High Medium (Data migration is tricky)

Warning: The “big rewrite” is a siren song for engineers. It’s tempting, but it’s also where projects go to die. Before you advocate for this, ensure you have a rock-solid plan, executive buy-in, and a clear understanding of what “done” looks like. Sometimes migrating to a competitor’s API or a better-suited open-source tool is the more pragmatic choice.

Ultimately, a slow app isn’t just an annoyance; it’s a sign of deeper architectural issues and a breakdown in the feedback loop between users and engineers. Whether you’re a frustrated user or the engineer on call, understanding the “why” is the first step to making things right.

Darian Vance - Lead Cloud Architect

Darian Vance

Lead Cloud Architect & DevOps Strategist

With over 12 years in system architecture and automation, Darian specializes in simplifying complex cloud infrastructures. An advocate for open-source solutions, he founded TechResolve to provide engineers with actionable, battle-tested troubleshooting guides and robust software alternatives.


🤖 Frequently Asked Questions

❓ How can I improve the performance of a slow Electron app like Notion on my personal machine?

To mitigate performance issues on your machine, use the web version if available, restart the app periodically to clear memory leaks, and employ network-level ad-blockers (e.g., Pi-hole, uBlock Origin) to block analytics and tracking scripts that add overhead.

❓ What are the primary architectural changes an engineering team can implement to fix a slow application?

Engineering teams should implement aggressive caching with CDNs for static assets, design smarter APIs (e.g., GraphQL or query parameters for REST) to prevent over-fetching, and utilize frontend build optimizations like code-splitting to load only necessary JavaScript chunks on demand.

❓ What is the ‘Nuclear Option’ for fixing a fundamentally flawed application architecture?

The ‘Nuclear Option’ involves evaluating whether to rebuild the application in-house or migrate to a better-suited existing tool. This is a high-effort, high-impact, and high-risk decision that requires strong executive buy-in and a clear plan to avoid the pitfalls of a ‘big rewrite’.

Leave a Reply

Discover more from TechResolve - SaaS Troubleshooting & Software Alternatives

Subscribe now to keep reading and get access to the full archive.

Continue reading