Flux.ai is a complex, single-page web app that helps electronic engineers design printed circuit boards. As with any professional design tool, it needs to be fast, precise and predictable.

Early versions of Flux.ai were noticeably slow. We set a goal of making all our user interactions take less than 100ms, supported by science. We started a plethora of projects to make that happen, one of which I wrote about in another blog post. To make sure these efforts paid off, we created a measurement tool, log-time-to-next-idle, that is the subject of this blog post.

We've been using it to track the performance of around 50 key user interactions over 18 months, such as:

  • Selecting a component
  • Start dragging a component
  • End dragging a component
  • Adding a trace
  • Switching camera modes

We're very happy with how it is working. And now we've shared it with the world as an open-source package.

What is a user interaction?

A user interaction is defined here as any input the user provides—mouse click, key press, and so on—coupled with the intended effects of the input—menu opened, element added, and so on. The performance of a user interaction is simply the time between the start of the input to the end of the effects. For example, clicking on a select box will open a menu. The interaction is done when the menu has finished loading.

A subset of the interaction time is defined as “frozen time”. This is the interval following the user input when there are zero screen updates––no animation frames.

How is a user interaction measured?

Although the concept of a user interaction is easy to define intuitively, the end state can be hard to define formally. In modern reactive UIs, any part of the UI can freely change in response to an update of a store of application state (Redux, Zustand, and so forth). The initial handler of some user input doesn't know all the downstream effects of its execution and so it can't mark the end of the interaction.

In the diagram above, it is hard to know which among the N components will determine the "end" of the interaction. You may not even know what are all the N components that react to some user inptu. To deal with this problem, we took a shortcut. Assuming that...

  1. The CPU is idle when there is no user input
  2. All effects of a user input happen immediately after the input with the highest priority
  3. All effects require CPU time
  4. The interaction is done when the CPU returns to idle

...we can leverage requestIdleCallback to mark when an interaction is done.

Similarly, we can leverage requestAnimationFrame to indicate when an interaction has yielded control back to the main thread, unfreezing the UI.

In short, log-time-to-next-idle measures user interactions by queuing a requestAnimationFrame and a requestIdleCallback at the start of an interaction, then recording the time when the callbacks fire.

Code sample

Just put a call to logTimeToNextIdle at the start of any event handler. Here is an example of logging the time it takes to switch fictional tabs in a React app.


const logTimeToNextIdle = require('log-time-to-next-idle')

// ...

// Inside the Tabs
  onChange={(_event, tabName) => {
    // This is where the magic happens
    logTimeToNextIdle(`switching-to-tab-${tabName}`);
    handleChange(tabName);
    // There is no need to mark the end of the interaction
    // You will see a message in the console like
    // "switching-to-tab-library took 27ms until unfrozen, 117ms until idle"
  }}
  
  Tab label="Library"
  Tab label="Objects"

Note on concurrency

log-time-to-next-idle deals with overlapping interactions by cancelling earlier queued callbacks. In other words, the last interaction "wins" and any previous in-progress interaction is ignored. For ease of interpretation, you should try to measure debounced interactions that happen one at a time.

Profiler integration

log-time-to-next-idle will store measured intervals in the browser using window.performance.measure (if available). The intervals will then show up in the profiler (if available).

Custom Logging

Here is an example that logs to the console when in dev build mode, and logs to somewhere in the cloud when in prod build.



// Inside the Tabs
  onChange={(_event, tabName) => {
    logTimeToNextIdle(`switching-to-tab-${tabName}`, (name, data) =>
      if (process.env.NODE_ENV === "development") {
        console.log(`${name} took ${data.durationInMs}ms`)
      } else {
        logSomewhere(name, {
          durationInMs: data.durationInMs,
        })
      }
    );
    handleChange(tabName);
  }}

  Tab label="Library"
  Tab label="Objects"

Conclusion

We hope this measurment function log-time-to-next-idle will be useful to you and your app, as well as the general approach of defining interaction end points in terms of CPU usage. Check out the open-source package and please post any feedback there.

Profile avatar of the blog author

Greg Dingle

Building the future with friends

Go 10x faster from idea to PCB
Work with Flux like an engineering intern—automating the grunt work, learning your standards, explaining its decisions, and checking in for feedback at key moments.
Illustration of sub-layout. Several groups of parts and traces hover above a layout.
Design PCBs with AI
Introducing a new way to work: Give Flux a job and it plans, explains, and executes workflows inside a full browser-based eCAD you can edit anytime.
Screenshot of the Flux app showing a PCB in 3D mode with collaborative cursors, a comment thread pinned on the canvas, and live pricing and availability for a part on the board.
Design PCBs with AI
Introducing a new way to work: Give Flux a job and it plans, explains, and executes workflows inside a full browser-based eCAD you can edit anytime.
Screenshot of the Flux app showing a PCB in 3D mode with collaborative cursors, a comment thread pinned on the canvas, and live pricing and availability for a part on the board.
Design PCBs with AI
Introducing a new way to work: Give Flux a job and it plans, explains, and executes workflows inside a full browser-based eCAD you can edit anytime.
Screenshot of the Flux app showing a PCB in 3D mode with collaborative cursors, a comment thread pinned on the canvas, and live pricing and availability for a part on the board.

Related Content

PCB Prototyping vs. Fabrication: Which Process Is Right for Your Project?

PCB Prototyping vs. Fabrication: Which Process Is Right for Your Project?

A practical guide to when hardware teams should use low-volume PCB prototyping to validate a design versus full-scale fabrication to scale production, and how to transition between the two without costly mistakes.

Profile avatar of Yaneev Hacohen
Yaneev Hacohen
|April 21, 2026
Blind Vias, Buried Vias, and Microvias: A Complete Guide to PCB Via Types

Blind Vias, Buried Vias, and Microvias: A Complete Guide to PCB Via Types

A practical guide to the four main PCB via types — through-hole, blind, buried, and microvia — covering how each is fabricated, their cost and signal-integrity trade-offs, and when to use them based on layer count, BGA pitch, and routing density.

Profile avatar of Yaneev Hacohen
Yaneev Hacohen
|April 21, 2026
PCB Design for Manufacturability (DFM): Rules and Best Practices

PCB Design for Manufacturability (DFM): Rules and Best Practices

Learn PCB design for manufacturability (DFM) guidelines, rules, and common issues to ensure your circuit boards can be reliably produced.

Profile avatar of Yaneev Hacohen
Yaneev Hacohen
|April 16, 2026
Best PCB Routing Techniques for Clean Circuit Board Layouts

Best PCB Routing Techniques for Clean Circuit Board Layouts

Learn the best PCB routing techniques for clean circuit board layouts, including trace routing tips, differential pair routing, and layout best practices.

Profile avatar of Yaneev Hacohen
Yaneev Hacohen
|April 16, 2026
High-Speed PCB Design: Layout Rules, Signal Integrity, and Routing Best Practices

High-Speed PCB Design: Layout Rules, Signal Integrity, and Routing Best Practices

Whether you're migrating from popular EDA applications or starting fresh, mastering high speed PCB design has never been more intuitive. Flux enables teams to design, simulate, and route with real-time AI assistance, so you can spin your next high-speed board with total confidence.

Profile avatar of Yaneev Hacohen
Yaneev Hacohen
|March 26, 2026
Design Rule Checking (DRC) in PCB Design: Real-Time vs Batch, Rules, and Common Failures

Design Rule Checking (DRC) in PCB Design: Real-Time vs Batch, Rules, and Common Failures

DRC is an automated process that checks your PCB layout against manufacturing and electrical constraints, catching errors like trace spacing and drill sizes before fabrication. Modern tools run this in real-time during design, while older ones batch-check at the end, often producing overwhelming error lists.

Profile avatar of Yaneev Hacohen
Yaneev Hacohen
|March 26, 2026
What Is a PCB? A Beginner's Guide to Printed Circuit Board Design

What Is a PCB? A Beginner's Guide to Printed Circuit Board Design

Whether you are exploring “What is a PCB?” for the first time or moving into advanced hardware engineering, modern tools make the process easier than ever. With Flux's AI-assisted platform, you can skip the steep learning curve of popular ECAD applications and design collaboratively directly in your browser. Once your board is routed and ready for fabrication, Flux's built-in supply chain features connect you directly with worldwide distributors to source parts instantly. Sign up for free today and start building!

Profile avatar of Yaneev Hacohen
Yaneev Hacohen
|March 21, 2026
Simulate Circuits with a Prompt

Simulate Circuits with a Prompt

Flux brings circuit simulation to wherever you are in the design process. Start from a prompt when you have no schematic, or let Flux analyze your existing design automatically.

Profile avatar of Lance Cassidy
Lance Cassidy
|March 20, 2026