Based on your code and the behavior you described, it appears that the issue stems from how the tap–hold state for your custom keycodes is managed. In your code (see keymap.c citeturn7file2), the variables   is_custom_key_pressed   custom_key_down are used to track any active custom key. However, this design assumes only one custom key is active at any one time. When you type very fast (for example, “r” from R_4, then “e” from E_3, then “s” which is a standard key), the following occurs: 1. **Global State Cancellation on Any Keypress:** In your process_record_user function you have this block: ``` if (is_custom_key_pressed && custom_key_down >= 0 && record->event.pressed) { register_code(custom_keys[custom_key_down][0]); wait_ms(35); unregister_code(custom_keys[custom_key_down][0]); custom_keys_tapped[custom_key_down] = true; custom_keys_timer[custom_key_down] = 0; custom_key_down = 0; is_custom_key_pressed = false; } ``` Because custom_key_down is an unsigned integer, it’s always ≥0. This condition fires on *any* subsequent keypress—even if that key is itself a custom key (like going from “R” to “E”). That cancels the pending tap action for the first custom key immediately, even if the new key is also custom. As a result, the release events and their timing get confused, and keys end up being sent in the wrong order. 2. **Out-of-Order Key Events:** When you press “r” (custom key R_4) and then “e” (custom key E_3), the pending state for “r” is canceled immediately by the arrival of the new key press; its tap code is issued with a delay (due to wait_ms(35)) before “e” is finally processed. This mismatch in timing causes “r” to be output after “e” instead of before, which is why you see “rse” rather than “res” when you type quickly. ### How to Fix It **a. Limit Cancellation to Non-Custom Keypresses** One approach is to modify the condition so that the tap–hold cancellation does not occur when the new key is itself a custom key. For example, change the check to something like:   if (is_custom_key_pressed &&     !(keycode >= Q_1 && keycode < END_TAP_HOLD_CUSTOM_KEYCODES) &&     record->event.pressed) {     // Cancel pending custom tap   } This change will ensure that a pending custom tap isn’t canceled by the press of another custom key. **b. Track Each Custom Key Independently** Another more robust solution is to avoid using a single global variable (custom_key_down) to track the active custom key. Instead, use an array or per-key state so that each custom key can be tracked independently. That way, fast sequences of custom key presses (like “r” then “e”) won’t interfere with each other. This approach would require a redesign of the tap–hold logic to process each key’s timer and tapped state separately rather than bundling them into a single global state. **c. Reconsider the use of wait_ms(35) in process_record_user** That 35‑ms delay was added to better match physical key press durations. However, in fast sequences this artificial delay might contribute to the reordering if multiple keys are being canceled and then re‑issued. You might consider if the delay can be reduced or moved so that it doesn’t interfere with the ordering when a cancellation occurs. ### Summary The core problem is that the current tap–hold cancellation logic runs whenever any key press occurs (due to the global use of is_custom_key_pressed and custom_key_down), even if that new key is another custom key. This causes a race where the tap event for the previously pressed key is canceled and re‑triggered out of order. Adjusting the cancellation condition to ignore subsequent custom keycodes or redesigning the state to track each key individually should help resolve the issue. I recommend starting with option (a) by modifying your condition in process_record_user to only cancel the pending custom key if the new key isn’t another custom key. Once that behavior is confirmed, you could explore a per-key tracking strategy for a more robust solution. Let me know if you need further details or have any questions about implementing these changes!