Skip to main content

Command Palette

Search for a command to run...

TanStack Pacer

Updated
4 min read
TanStack Pacer

TanStack Pacer is a library from the TanStack team where they share the high quality utilities for controlling function execution timings in the applications.

TanStack Pacer is currently a client-side only library but it is designed to be used in server-side as well.

Features of TanStack Pacer

  1. Debouncing - Delay execution until after a period of inactivity for when you only care about the last execution in a sequence.

  2. Throttling - Smoothly limit the rate at which a function can fire

  3. Rate Limiting - Limit the rate at which a function can fire over a period of time

  4. Queuing - Queue functions to be executed in a specific order, Choose from FIFO, LIFO, and Priority queue implementations

  5. Batching - Chunk up multiple operations into larger batches to reduce total back-and-forth operations

  6. Async or Sync Variations - Choose between synchronous and asynchronous versions of each utility

  7. State Management - Uses TanStack Store under the hood for state management with fine-grained reactivity

  8. Convenient Hooks - Reduce boilerplate code with pre-built hooks like useDebouncedCallback, useThrottledValue, and useQueuedState, and more.

  9. Tree-shaking - Get tree-shaking right for your applications by default

  10. Type safety - Full type safety with TypeScript that makes sure that your functions will always be called with the correct arguments

Installation

You can install TanStack Pacer.

To install it in React you can use the below command

npm install @tanstack/react-pacer

To use the devtools for debugging and monitoring, install both the framework devtools and the Pacer devtools packages

npm install @tanstack/react-devtools @tanstack/react-pacer-devtools

Debouncing

Debouncing is a technique that delays the execution of a function until a specified period of inactivity time occured

"use client"
import { useState, useEffect } from "react"
import { useDebouncedValue } from "@tanstack/react-pacer"

export default function ProductSearch() {
  const [input, setInput] = useState("")
  const [results, setResults] = useState<string[]>([])

  // Debounce input by 400ms
  const [debouncedInput] = useDebouncedValue(input, { wait: 400 })

  useEffect(() => {
    if (!debouncedInput) {
      setResults([])
      return
    }

    const fetchData = async () => {
      const response = await fetch(`/api/products?query=${debouncedInput}`)
      const json = await response.json()
      setResults(json.items)
    }

    fetchData()
  }, [debouncedInput])

  return (
    <div className="space-y-2">
      <input
        className="border p-2 w-full"
        placeholder="Search products..."
        value={input}
        onChange={(e) => setInput(e.target.value)}
      />

      {/* Render suggestions */}
      {results.length > 0 && (
        <ul className="border rounded p-2 bg-white">
          {results.map(item => (
            <li key={item} className="py-1 border-b last:border-none">
              {item}
            </li>
          ))}
        </ul>
      )}
    </div>
  )
}

The above example updates the url after 400ms

Throttling

Throttling ensures function executions are evenly spaced over time. Unlike rate limiting which allows bursts of executions up to a limit, or debouncing which waits for activity to stop, throttling creates a smoother execution pattern by enforcing consistent delays between calls.

"use client"
import { throttle } from "@tanstack/react-pacer"

export default function SafeButton() {
  const handleClick = throttle(() => {
    alert("Action performed")
  }, { wait: 1000 }) // only allowed once per second

  return (
    <button
      onClick={handleClick}
      className="px-4 py-2 bg-blue-600 text-white rounded"
    >
      Click Me Fast — I’m Throttled
    </button>
  )
}

Throttled Button (prevents spam clicks) useful for API calls, forms submission or payment prompts

Rate Limiting

Rate Limiting is a technique that limits the rate at which a function can execute over a specific time window. It is particularly useful for scenarios where you want to prevent a function from being called too frequently, such as when handling API requests or other external service calls.

import { rateLimit } from "@tanstack/react-pacer"

const safeLogin = rateLimit(
  async (email: string, password: string) => {
    console.log("Login attempted")
    // Backend login API here
    return { success: true }
  },
  { limit: 3, interval: 30_000 } // allow 3 attempts every 30s
)

// Usage
safeLogin("user@mail.com", "pass123").then(console.log)
safeLogin("user@mail.com", "pass123").then(console.log)
// 4th call within 30s will be rate-limited

Queuing

Queuing ensures that every operation is eventually processed, even if they come in faster than they can be handled. Unlike the other execution control techniques that drop excess operations, queuing buffers operations in an ordered list and processes them according to specific rules.

import { queue } from "@tanstack/react-pacer"

const writeToDB = queue(
  async (record: any) => {
    console.log("Writing record:", record.id)
    await fetch("/api/db/save", {
      method: "POST",
      body: JSON.stringify(record),
      headers: { "Content-Type": "application/json" }
    })
  },
  { concurrency: 3 } // controlled parallelism
)

// Usage
records.forEach(r => writeToDB(r))

Queue Database Writes to Avoid Locking. Batch DB operations without hammering the server.

Batching

Batching collects items over time or until a certain size is reached, then processes them all at once. This is ideal for scenarios where processing items in bulk is more efficient than handling them one by one.

import { batch } from "@tanstack/react-pacer"

const queueMessages = batch(async (msgs: string[]) => {
  await fetch("/api/messages/bulk", {
    method: "POST",
    body: JSON.stringify(msgs),
    headers: { "Content-Type": "application/json" }
  })
}, { maxSize: 20, wait: 1500 }) // send when 20 msgs or 1.5s idle

// Usage
queueMessages("Hello")
queueMessages("How are you?")
queueMessages("What's new?")

Batch messages before sending to server. Reduces network calls by grouping multiple messages.

Final Notes

Using the Tanstack Pacer in your application helps precise control over function execution, leading to smoother UX, reduced API costs, and improved performance. Whether you’re handling user input, managing API calls, or orchestrating complex async workflows, these utilities are your one-stop shop for execution timing

More from this blog

Nidhin's blog

168 posts

✨Crafting Code with a Smile for 8 Years:) Merging the Formal Dance of Angular, the Playful Rhythms of React, and the Next-level Moves of Next.js 🚀