95% of users will never use your app again without this JavaScript feature

Without this JaaScript you will waste thousands of dollars and users will hate your app.

1. They will hate your app

They will be irritated by the horrible user experience and never return.

So imagine you’ve created an amazing AI writing assistant giving helpful suggestions for writing engaging stories:

You’ve got your API all set up for requests in handleChange:

JavaScript
export function AssistantUI() { const [suggestions, setSuggestions] = useState(''); const [loading, setLoading] = useState(false); const handleChange = async (event: any) => { const value = event.target.value; setLoading(true); const res = await fetch( 'https://api.writer.example.com/suggestions', { method: 'POST', body: JSON.stringify({ text: value }), } ); const json = await res.json(); setSuggestions(json.suggestions); setLoading(false); }; return ( <div className="flex flex-col justify-center flex-wrap content-start"> <textarea onChange={handleChange} className="mt-2 mb-4" cols={40} rows={10} /> { //... } </div> ); }

But unfortunately there’s a serious problem — can you spot it? 👇

I just started writing and immediately your AI is telling me nonsense about wrong spelling!

Where is my breathing space? Can’t you at least allow me to stop typing?

Oh no, I’m done — You ruined my day and I’ll never return.

But luckily that was just you in an alternate reality — the real you already knew that such UX would be annoying at best and infuriating at worst.

You’re so thoughtful and empathetic — that was why you knew this was a much better way to write handleChange:

JavaScript
export function AssistantUI() { const [suggestions, setSuggestions] = useState(''); const [loading, setLoading] = useState(false); const timeout = useRef<NodeJS.Timeout | null>(null); const handleChange = async (event: any) => { const value = event.target.value; setLoading(true); // restart delay clearTimeout(timeout.current!); // ✅ 1-second delay before fetch timeout.current = setTimeout(async () => { const res = await fetch( 'https://api.writer.example.com/suggestion', { method: 'POST', body: JSON.stringify({ text: value }), } ); const json = await res.json(); setSuggestions(json.suggestions); setLoading(false); }, 1000); }; return ( // ... ); }

Now the AI waits for 1 second before giving suggestions!

Everybody is in love with your app now – we could even stop using it if we tried…

In programming, we call this technique debouncing.

And it shows up everywhere…

  • Google Search: Any time you search, you’re experiencing debouncing in action.

Notice the delay between typing and the autocomplete update. It’s not latency, it’s debouncing.

  • Conversation: When we’re debating and you let me make my points before responding, you’re debouncing.

You didn’t interrupt and start screaming — you made sure I was done by constantly setting a subconscious timeout until I finally stopped speaking:

JavaScript
let silenceTimeout; let silenceDelay = 1000; function opponentKeepsTalking() { clearTimeout(silenceTimeout); silenceTimeout = setTimeout(() => { reply('Your fallacious premises have no basis in reality'); }, silenceDelay); }

2. You lose thousands of $$$

Your users are not the only ones getting overloaded — your servers are crying out for help.

❌ Before debounce:

1,000 users typing 10 times a second = 10 x 60 x 1000 = 600,000 requests a minute!

This load isn’t a functional issue with cloud computing but what about the costs?

Especially since you’re probably using an expensive AI service like OpenAI or GCP Vertex.

✅ Now after debounce:

Typing frequency no longer matters — if they pause typing 10 times every minute that’s

10 x 1000 = 10,000 requests a minute! A 98.3% reduction in requests and costs!

You were spending $1000 a day but now you’re spending less than $170 (!)

What took you a day to spend now takes you a week. Thanks to debounce.

But you can do better

Okay but that’s still like $5,000 a month — can’t we do better?

90% of your users are free and we need to keep their usage at a bare minimum.

Luckily you’re really smart so you quickly came up with this:

JavaScript
const timeout = useRef<NodeJS.Timeout | null>(null); const ignoring = useRef<boolean>(false); const handleChange = async (event: any) => { if (plan === 'free') { // ✅ still ignoring so nope if (ignoring.current) return; // ✅ start ignoring for 20 seconds ignoring.current = true; setTimeout(() => { ignoring.current = false; }, 20 * 1000); } // after throttle debounce(); const value = event.target.value; setLoading(true); const res = await fetch( 'https://api.writer.example.com/suggestion', { method: 'POST', body: JSON.stringify({ text: value }), } ); const json = await res.json(); setSuggestions(json.suggestions); setLoading(false); };

You ignore free users for 20 seconds after getting their last suggestion.

So only 3 suggestions per minute for them.

900 free users, 100 paying.

900 x 3 + 100 x 10 = 3,700 requests a minute — from $5,100 to $1900.

Killing two birds with one stone:

  • Massive 63% savings
  • Incentivize free users to upgrade for unlimited suggestions.

This is another technique we call throttling.

And it shows up anywhere you have periodically limited access to something:

  • GPT-4o model: Only allow 80 messages every 3 hours for Plus users, as of May 13th 2024.
  • Eating: You can only gobble up so much food at a time

Recap from our earlier debate:

  • Debounce: You wait for me to finish talking before responding and vice versa.
  • Throttle: We both have 5 minutes max at a time to talk.

With this powerful combo, what lasted only one day now lasted 3 weeks.

600,000 requests became 3,700, everyone loves your app, and you’re going to be a billionaire.



11 Amazing New JavaScript Features in ES13

This guide will bring you up to speed with all the latest features added in ECMAScript 13. These powerful new features will modernize your JavaScript with shorter and more expressive code.

11 Amazing New JavaScript Features in ES13

Sign up and receive a free copy immediately.

Leave a Comment

Your email address will not be published. Required fields are marked *