Proposal: Add a trailing option to phx-throttle to ensure the last event is always emitted

I’d like to propose adding a trailing option to phx-throttle so that the final event in a burst is always delivered — similar to throttling utilities in other ecosystems.

:light_bulb: What I’m suggesting

phx-throttle currently limits how frequently events are pushed, but it does not ensure that the last event will be sent within the throttling window.

I’m proposing an optional flag such as:

phx-throttle="200" phx-throttle-trailing

(or trailing=“true” depending on conventions)

which would guarantee that after throttling settles, the most recent event is emitted.

:rocket: Why this matters in real-world LiveView apps

In many cases, developers choose debounce for inputs, but the downside is that it delays the UI response. For example:

  • typing into a search box

  • adjusting a slider

  • interacting with fast-changing inputs

Debounce waits until the user stops typing, which means the UI feels less responsive.

On the other hand, throttle emits the first event immediately, giving users instant feedback, while still reducing server load. But without a trailing event, we lose the final accurate state, which is often essential for real-time interactions.

A trailing option would let us enjoy the best of both worlds:

  • fast first response → smoother UX and more responsive LiveView apps

  • controlled message rate → reduced load on the server

  • final correct value → no need for hacks like extra phx-blur events or custom JS hooks

I believe this would significantly improve customer experience in LiveView applications, especially in dynamic, interactive UI scenarios.

Thanks!

3 Likes

I believe we made it so we always send the last event on focus out, or does that do not apply to throttle? In any case, I don’t think we should make this an option but rather make it so after the throttle window is closed, we emit the last event in the last window (starting a new throttle window)?

We did some changes, but had to revert them because they introduced another bug and made the already complicated code more complicated.

Quoting from undo debounce/throttle changes by SteffenDE · Pull Request #3108 · phoenixframework/phoenix_live_view · GitHub, we decided that sending the current value on blur should be done explicitly if needed:

This PR adjusts the throttle code in a minimal approach to allow the use cases where the user wants to get the latest value on blur when throttle is used. In these cases, simply adding a phx-blur={JS.dispatch("change")} is the way to go:

<input
  name="tick_frequency"
  type="range"
  min="100"
  max="1000"
  value={@tick_frequency}
  phx-throttle="2000"
  phx-change="change-tick-frequency"
  phx-blur={JS.dispatch("change")}
/>

@nallwhy if you want to invest time and try to make this work, we’d be happy to review, but please try to read through the issues linked in the PR above to avoid doing the same mistakes I did :sweat_smile:

7 Likes