How to Reduce Controller Input Latency on Mac

Your controller feels delayed not because the hardware is slow but because every mapper has to wait to see if you're starting a chord. ControllerKeys has a per-profile switch that turns that wait off for simple keys.

Why Controllers Feel Laggy as Keyboards

Press the spacebar on a real keyboard and the key-down event is delivered to the focused app the moment the key crosses the actuation point. The OS doesn't wait to see if you might be starting a keyboard shortcut. There's nothing to wait for — chords on a keyboard are simultaneous presses, identified by which keys are currently held.

Controllers are different. A "chord" on a controller is "press these two buttons within a short window of each other." If you press A, the mapper has to wait briefly to see if B is about to follow — because A alone and A+B can be bound to different actions. Most mappers use a window of 30–80 milliseconds. That window is invisible during productivity use, but very visible during fast-twitch input — and very visible during latency benchmarks.

The Anatomy of Controller-Through-Mapper Latency

Stage Approx. cost Affected by
Controller hardware → OS HID 1–8 ms Controller polling rate, USB vs Bluetooth
OS HID → mapper < 1 ms macOS run loop scheduling
Chord-detection window 30–80 ms Mapper config — this is the big one
Mapper → CGEvent post < 1 ms Mapper code path
CGEvent → focused app 1–4 ms macOS event tap chain

If you're chasing real latency improvements, the chord-detection window is where 80% of the savings live. The other stages add up to single-digit milliseconds and there's not much a user-space app can do about them.

What Realtime Input Mode Does

ControllerKeys 1.8.2 introduced realtime input mode as a per-profile setting. When it's on:

In practice, realtime mode shaves the entire chord-detection window off any simple key. A button bound to "Tab" feels indistinguishable from pressing Tab on a real keyboard.

How to Enable It

1

Activate the Target Profile

Realtime mode is per-profile, so make sure the profile you want to make low-latency is the active one. You can flip it on for a single context (a specific app, a streaming setup, a game) and leave your everyday productivity profile on Standard timing.

2

Open Hardware → Input

In the main window, open the Hardware tab. The Input section is near the top, alongside a Standard / Realtime segmented picker.

3

Pick Realtime

Switch the picker from Standard to Realtime. A summary panel updates to confirm the change: "Fires eligible key mappings immediately on button press" and "Plain one-button key mappings only. Advanced mappings automatically stay on standard timing."

4

Test a Simple Mapping

Bind a button to a single keystroke. Press it. It should feel indistinguishable from pressing the key directly on the keyboard.

When to Turn It On vs Leave It Off

Turn It On

  • You're using the controller for a fast-twitch game
  • You're driving a demo or recording a screencast and any latency is visible
  • Most of your bindings are single keys, not chords
  • You're running benchmarks against the controller

Leave It Off

  • You rely heavily on chords (multi-button bindings)
  • Your workflow is comfortable with the default timing
  • You can't tell the difference (you're not missing anything if so)

Other Latency Wins (Independent of Realtime Mode)

Why Not Always-On?

The default ChordKeys timing exists because most ControllerKeys users do use chords. If realtime mode were always on, every chord would fire the first button's binding briefly before the second button arrived and corrected it — a flash of the wrong action on every chord press. The default behavior trades a small latency for that correctness.

Making it per-profile gives you both: an "everyday productivity" profile with chord-friendly timing, and a "fast input" profile with the wait turned off, switched automatically by app focus or by a button press.

Get the Fastest Controller-to-Keyboard Mapper on Mac

Realtime input mode is one of about 50 features in ControllerKeys. Layers, chords, sequences, scripts, webhooks, Mac-to-Mac handoff, and per-app profiles round out the rest.

Related Guides