Linux DJ
Terminal showing real-time process priorities on a Linux system
Low Latency·/latency/

PipeWire Real Time Scheduling in 2026: RTKit, Portal Realtime, and rlimits for Musicians Who Just Want Low Latency

Three ways PipeWire gets real-time scheduling on Linux. RTKit, portal realtime, and traditional rlimits - which one your system is actually using and whether it is enough for serious audio work.

You have set your PipeWire quantum to 128. You have configured WirePlumber properly. You are still getting XRuns that do not correlate with CPU load. The problem is almost certainly real-time scheduling - PipeWire's audio thread is not getting to run when it needs to because the kernel scheduler is treating it like a normal process.

Real-time scheduling is the mechanism that tells the Linux kernel "this thread must run before anything else when it wakes up." Without it, PipeWire's audio processing thread competes with your file manager indexing, your browser rendering, and every other normal-priority task. At quantum 256 (5.33 ms budget at 48 kHz), you might get away with it. At quantum 128 or 64, you will not.

There are three mechanisms PipeWire uses to acquire real-time scheduling priority on modern Linux. All three achieve the same goal through different paths, and your system is probably using only one of them.

The three mechanisms

1. RTKit (RealtimeKit) via D-Bus

RTKit is a D-Bus system service that grants limited real-time scheduling to requesting processes. PipeWire connects to org.freedesktop.RealtimeKit1 on the system bus and asks for SCHED_FIFO priority.

RTKit was the original solution for desktop audio. It is conservative by design:

  • Default maximum priority: 20 (out of 99)
  • Default maximum nice value: -15
  • Per-user thread limits apply
  • RTKit validates that the requesting process is not asking for more than the configured ceiling

Check if RTKit is running:

systemctl status rtkit-daemon

Check what PipeWire actually got:

# Find PipeWire's audio thread
ps -eLo pid,tid,cls,rtprio,ni,comm | grep pipewire

Look for the FF scheduling class (SCHED_FIFO) and the RTPRIO column. If you see RR or TS, RTKit either failed or was not used.

The problem with RTKit for serious audio work is that priority ceiling. SCHED_FIFO 20 means PipeWire's audio thread runs before all normal processes, but after any thread with priority 21 or higher. Kernel IRQ threads, some USB subsystem threads, and other real-time tasks can preempt it. At low quanta, this matters.

2. xdg-desktop-portal realtime interface

The xdg-desktop-portal project added a Realtime interface that provides real-time scheduling through the user session's portal. PipeWire 0.3.50+ can use this instead of or alongside RTKit.

The portal approach has advantages for Flatpak and sandboxed environments because the portal broker runs outside the sandbox and can grant privileges the sandboxed process cannot acquire directly. For non-sandboxed PipeWire installations, the portal typically delegates to RTKit anyway, so the effective ceiling is the same.

Check if the portal realtime interface is available:

busctl --user introspect org.freedesktop.portal.Desktop \
  /org/freedesktop/portal/desktop org.freedesktop.portal.Realtime

If this returns method signatures, the portal interface is available. If it returns an error, your portal installation does not include the realtime interface.

3. rlimits (resource limits)

The traditional Unix approach. If the user running PipeWire has a high enough RLIMIT_RTPRIO, PipeWire can set its own real-time priority directly without involving any intermediary service.

This is the most direct and usually the most effective method. It removes the RTKit ceiling entirely and lets PipeWire set whatever priority it is configured for (typically SCHED_FIFO 88 in the default config).

Check your current rlimits:

ulimit -r

If this returns 0, you have no real-time privilege. If it returns a number, that is your maximum allowed SCHED_FIFO priority.

Comparison

FeatureRTKitPortal Realtimerlimits
Max SCHED_FIFO priority20 (default)20 (delegates to RTKit)Up to 99
Requires system serviceYes (rtkit-daemon)Yes (xdg-desktop-portal)No
Works in FlatpakYesYes (primary method)No
Configuration location/etc/dbus-1/Portal configlimits.conf or systemd
Latency suitabilityModerate (256+)Moderate (256+)Aggressive (64-128)
Distribution defaultMost desktopsGNOME, KDE on WaylandAudio-focused distros

For musicians targeting low latency, rlimits is the answer. RTKit gets you started; rlimits gets you there.

How to check which mechanism is active

PipeWire logs which method it used to acquire real-time scheduling. Check the journal:

journalctl --user -u pipewire -b | grep -i "rt prio\|realtime\|rtkit\|rlimit"

You will see messages like:

  • RTKit: acquired realtime priority 20 - Using RTKit
  • using realtime portal - Using portal interface
  • acquired SCHED_FIFO priority 88 - Using rlimits directly

If you see could not acquire realtime priority or similar, none of the mechanisms worked and PipeWire is running as a normal-priority process. This is the primary cause of unexplained XRuns at low quanta.

When RTKit is not enough

RTKit's default ceiling of SCHED_FIFO 20 is sufficient for casual audio use at quantum 256 or higher. It falls short when:

  • You need quantum 128 or lower for live monitoring
  • Your system runs other real-time tasks (MIDI sequencers, video capture) that compete at similar priorities
  • Kernel IRQ threads (particularly USB host controller threads) preempt the audio thread during critical periods
  • You have a high-interrupt-rate device (some network adapters, GPU drivers) generating work above priority 20

The tell-tale sign is XRuns that appear sporadically and do not correlate with CPU load or plugin count. Your processing completes in time, but the thread did not get to run when it woke up because something else was holding the CPU at a higher priority.

The latency data we collect shows the measurable difference between RTKit-limited and properly configured rlimits setups. It is significant at quanta below 256.

Configuring rlimits properly

Method 1: limits.conf

The traditional approach using PAM limits:

# /etc/security/limits.d/audio.conf
@audio   -  rtprio     95
@audio   -  memlock    unlimited
@audio   -  nice       -20

Then add your user to the audio group:

sudo usermod -aG audio $USER

Log out and back in for the group membership to take effect. Verify:

ulimit -r
# Should return: 95
ulimit -l
# Should return: unlimited

The memlock setting matters too. PipeWire and JACK applications lock audio buffers in memory to prevent page faults during processing. Without unlimited memlock, large projects can trigger swapping in the audio path.

Method 2: systemd user unit override

If your distribution uses systemd for user sessions (most do in 2026), you can set rlimits directly on the PipeWire service:

mkdir -p ~/.config/systemd/user/pipewire.service.d/
# ~/.config/systemd/user/pipewire.service.d/realtime.conf
[Service]
LimitRTPRIO=95
LimitMEMLOCK=infinity
LimitNICE=-20

Reload and restart:

systemctl --user daemon-reload
systemctl --user restart pipewire pipewire-pulse wireplumber

Verify it took effect:

cat /proc/$(pidof pipewire)/limits | grep -i "realtime\|locked"

The systemd method is cleaner because it does not depend on PAM, does not require group membership changes, and applies only to PipeWire rather than to all processes run by the user.

Which priority number?

PipeWire defaults to requesting SCHED_FIFO 88 when rlimits allow it. This is a sensible default:

  • High enough to preempt almost all normal system activity
  • Below the kernel's default IRQ thread priorities (typically 50)
  • Leaves headroom for urgent kernel threads at 99

Wait - IRQ threads default to priority 50 and PipeWire asks for 88? Yes, PipeWire's audio thread at 88 preempts default IRQ threads at 50. This is intentional for audio workloads. The kernel's threaded interrupt handlers run at 50 by default, and audio processing at 88 ensures the audio deadline is met even when an IRQ handler is pending. If this concerns you, it should - on a general server workload this would be wrong. For a dedicated audio machine, it is correct.

You should not set PipeWire's priority higher than 95. Priorities 96-99 are conventionally reserved for kernel watchdog threads and critical system functions.

Common failures and diagnostics

rlimits set but PipeWire still uses RTKit. PipeWire checks rlimits first, then falls back to RTKit. If rlimits appear set but PipeWire is not using them, the most common cause is that you changed limits.conf but did not log out and back in. PAM limits are applied at login time. Alternatively, if PipeWire is started by a systemd user unit, PAM limits from limits.conf may not apply - use the systemd override method instead.

Priority 20 despite rlimits being 95. Check that PipeWire's configuration does not explicitly cap the priority. Look in:

grep -r "rt.prio" ~/.config/pipewire/ /etc/pipewire/

If you find rt.prio = 20 in a config file, it is overriding the rlimit ceiling.

PipeWire starts but audio thread is not real-time. Some container environments (Docker, systemd-nspawn) strip real-time capabilities. Check:

cat /proc/$(pidof pipewire)/status | grep CapEff
capsh --decode=$(cat /proc/$(pidof pipewire)/status | grep CapEff | awk '{print $2}')

Look for cap_sys_nice in the decoded capabilities. Without it, real-time scheduling is unavailable regardless of rlimits.

XRuns only when running alongside a specific application. Some applications (notably Wine/Proton for gaming, some video editors) also request real-time scheduling. If they request a priority equal to or higher than PipeWire's, they can preempt the audio thread. Check all SCHED_FIFO threads:

ps -eLo pid,tid,cls,rtprio,comm | grep FF | sort -k4 -n

If you previously configured your PipeWire quantum using the test method and found a stable value, but you are now seeing XRuns after changing real-time scheduling settings, re-run the quantum test. The threshold may have shifted because the audio thread is now actually preempting (or being preempted by) different threads.

For how WirePlumber's session management interacts with real-time scheduling and device priority, see the WirePlumber pro-audio profile guide.

FAQ

Do I need a real-time kernel for PipeWire? Not necessarily. The PREEMPT_DYNAMIC kernel config (default in most distributions since kernel 6.x) provides sufficient preemption for quantum 128 and above when combined with proper rlimits. A full PREEMPT_RT kernel helps at quantum 64 and below by making all kernel code preemptible, reducing worst-case scheduling latency. Check your kernel:

uname -v
# Look for PREEMPT_DYNAMIC or PREEMPT_RT
cat /sys/kernel/realtime
# Returns 1 if PREEMPT_RT

Is there a performance cost to SCHED_FIFO? Not for the audio thread itself. The thread only runs when PipeWire wakes it for processing. Between cycles, it sleeps and consumes zero CPU. The scheduling class only affects what happens when it wakes up - SCHED_FIFO ensures it runs immediately rather than waiting in the scheduler's fair queue.

Can I give individual plugins real-time priority? Plugins run within the host application's process. If PipeWire has real-time priority, the audio processing callback that runs plugins inherits that priority. You do not need to configure individual plugins. If a plugin spawns its own threads (some convolution reverbs do), those threads will not automatically inherit real-time priority.

RTKit keeps logging warnings about thread limits. Is this a problem? If PipeWire is successfully using rlimits (check the journal), RTKit warnings are noise. PipeWire tried RTKit, found rlimits were better, and is using those instead. The RTKit attempt generated the warning. You can safely ignore it, or disable RTKit if nothing else uses it.

Conclusion

Real-time scheduling is the second piece of the low-latency puzzle, after quantum selection. Get your rlimits configured through either limits.conf or systemd unit overrides, verify with ps and /proc that PipeWire actually acquired the priority it requested, and then re-test your quantum threshold. The difference between RTKit's priority 20 and rlimits at priority 88 is the difference between "quantum 128 sometimes works" and "quantum 128 is solid." For the latency numbers that matter to working musicians, that difference is measurable.

  • PipeWire
  • Real-Time
  • RTKit
  • rlimits
  • Low Latency
  • Linux Audio
  • 2026

Related Notes

← All notes