Yesterday I shipped my biggest ever React App performance improvement. You'll never guess what the tiny change was 😛
Today I shipped my biggest ever React App performance improvement. Smöl tweak, huge stepwise impact.
— Swizec Teller (@Swizec) January 30, 2023
it was a backend change
After working on a React app for 2.5 years, it was starting to feel clunky. Nothing obvious, just a general sense of clunky slowness.
But hey, at almost 40,000 lines of code and hundreds of unique components, maybe that's expected? We are running a lot of code and throwing around many re-renders.
Users were starting to notice. My girlfriend uses our app and she always tells me "Your thing is slow as shit". But user metrics looked good so this wasn't prioritized.
Until last week our platform team raised the alarm.
To the metrics!
"Emergency meeting! Wtf are you people doing with our server?"
Our server was struggling. Had been for months. The platform team fixed all they could, now they needed help from us product teams. What the hell are our clients doing to this thing?
We run a single server with one Node process for reasons too long to explain. When a request takes its time, the whole server slows down. Even other unrelated requests. The single-threaded nature of JavaScript means requests can impact each other.
Here's a good article, if you wanna read more about the details of Node's event-loop model and how it impacts performance.
The team constructed an API impact chart for us. Number of requests per week * p95 latency.
We are fetching a patient's appointments 1,000,000+ times per week and 95% of those requests "take less than 1.1 seconds". We have a few thousand users 🤨
Impact: over one billion.
An old sin
At this point I got a tingle in the back of my brain. "Aren't we always joking that our backend-for-the-frontend loads appointments on every request?"
Oral tradition is important. Those little jokes, japes, and anecdotes are your lore. They survive when teams evolve and they hold a nugget of truth. Like a myth based on reality.
We dug in and yep, deep in our session middleware, a line of code that pre-fetches appointments from the data server. On every request.
A 4 year old performance optimization nobody needs. A backlog ticket from 2021 when someone found this, but couldn't remove.
The one line fix
We looked and the code was dead. Anything that used session data had been moved to React by now and would load its own data when needed.
The fix was simple:
Sometimes the best fix is a smöl change after a long investigation.
My coworker left a pull request comment that I will frame and put on the wall in my office ❤️
<3 honestly, this is probably the most impactful removal of a single line of code in Tia's history. And it was entirely enabled by the transition to React. Great job :)
Did performance improve?
Yes!
Preliminary estimates show we went from calling that endpoint 150,000x/day to about 1,000x/day. p95 latency dropped by half. Server's less busy 😅
You can even see when the fix went live on a chart of database CPU usage.
And yes, the app feels subjectively snappier. Or I'm imagining it. It's hard to tell. But I can tell you this: every API request the app makes is faster. Up to 1 second faster. Because it doesn't pre-load appointments.
✌️
Cheers,
~Swizec
PS: for another fun story about following metrics to the unlikeliest of places, check out Immutability isn't free
Continue reading about My biggest React App performance boost was a backend change
Semantically similar articles hand-picked by GPT-4
- 90% of performance is data access patterns
- Why serverless fits side-projects perfectly
- How to rewrite your app while growing to a $100,000,000 series B
- Immutability isn't free
- Logging 1,721,410 events per day with Postgres, Rails, Heroku, and a bit of JavaScript
Learned something new?
Read more Software Engineering Lessons from Production
I write articles with real insight into the career and skills of a modern software engineer. "Raw and honest from the heart!" as one reader described them. Fueled by lessons learned over 20 years of building production code for side-projects, small businesses, and hyper growth startups. Both successful and not.
Subscribe below 👇
Software Engineering Lessons from Production
Join Swizec's Newsletter and get insightful emails 💌 on mindsets, tactics, and technical skills for your career. Real lessons from building production software. No bullshit.
"Man, love your simple writing! Yours is the only newsletter I open and only blog that I give a fuck to read & scroll till the end. And wow always take away lessons with me. Inspiring! And very relatable. 👌"
Have a burning question that you think I can answer? Hit me up on twitter and I'll do my best.
Who am I and who do I help? I'm Swizec Teller and I turn coders into engineers with "Raw and honest from the heart!" writing. No bullshit. Real insights into the career and skills of a modern software engineer.
Want to become a true senior engineer? Take ownership, have autonomy, and be a force multiplier on your team. The Senior Engineer Mindset ebook can help 👉 swizec.com/senior-mindset. These are the shifts in mindset that unlocked my career.
Curious about Serverless and the modern backend? Check out Serverless Handbook, for frontend engineers 👉 ServerlessHandbook.dev
Want to Stop copy pasting D3 examples and create data visualizations of your own? Learn how to build scalable dataviz React components your whole team can understand with React for Data Visualization
Want to get my best emails on JavaScript, React, Serverless, Fullstack Web, or Indie Hacking? Check out swizec.com/collections
Did someone amazing share this letter with you? Wonderful! You can sign up for my weekly letters for software engineers on their path to greatness, here: swizec.com/blog
Want to brush up on your modern JavaScript syntax? Check out my interactive cheatsheet: es6cheatsheet.com
By the way, just in case no one has told you it yet today: I love and appreciate you for who you are ❤️