← Blog

Why Grit is native

Grit started as an Electron app. It is now a Rust application with a hard real-time audio engine. Here is why, and what that changes on stage.

Bijan Rahnema 3 min read

The first version of Grit was a web app in a desktop wrapper: Electron for the window, Svelte for the interface, Tone.js for the audio. It was a good way to find out what the instrument should be. Multi-deck playback, bar-quantized launches, stem switching, EQ, filters and a crossfader all worked, and a simplified version of that prototype now sketches the idea in the playground on the home page.

It was not a good way to play a set. So Grit was rewritten as a native application.

What a performance needs

A DJ tool has one job that outranks everything else: the audio must not stop. Not when you load a track, not when you scroll the library, not when a file turns out to be broken, not when the interface is busy drawing eight waveforms.

In a browser engine, audio shares a process with layout, garbage collection, JavaScript and everything else the page is doing. You can work around that for a demo. You cannot rule it out.

How Grit is built now

Grit is written in Rust. The interface uses GPUI, a GPU-accelerated UI framework, and everything else sits behind a UI-independent application core.

A hard real-time audio callback

The audio callback is the code that fills your sound card's buffer, many times per second. In Grit it has a strict contract. It pops audio that was prepared in advance, mixes it, advances the clock and applies fixed-cost DSP. It never:

  • allocates memory,
  • takes a lock or waits on another thread,
  • decodes a file,
  • touches the disk,
  • or runs an unbounded loop.

Decoding, analysis and file work happen on other threads and hand finished audio to the callback through preallocated, lock-free queues. If something upstream is slow, the callback still meets its deadline.

Bounded by design

Memory and CPU use are bounded rather than best-effort. Tracks stream from disk instead of being held in memory, queues have fixed capacities, and background work is admitted in limited slots. A large library or a long session should not slowly change how the app behaves.

This is measured, not assumed. A headless release gate in development runs eight keylocked, phase-bent streams plus a preview stream. On 12 September 2026, a 30-second run passed with zero decoder underruns or callback deadline misses, 6.40% p99 callback CPU load and 34.83 MiB peak resident memory. That is a headless development measurement, not a test on physical audio hardware. Qualification on real hardware is still open, and it is part of the work before launch.

Broken files stay contained

Audio files come from everywhere, and some of them are malformed. Grit never parses foreign media inside the app. Imported audio and cover images go through a separate import helper process, one file per run, with limits on time and memory. If a file crashes the helper, only that import fails. The app and anything playing keep running.

Once imported, a track is stored as a managed FLAC file that Grit wrote itself, so playback only ever reads audio it knows.

Stems on your Mac

Stem separation and analysis run locally with Apple's MLX on Metal. There is no bundled Python interpreter, no Node.js runtime and no browser engine in the app. Your music is not uploaded for processing, and preparing a track does not depend on a service being online.

No server on stage

Nothing in a performance depends on a network connection. There is no cloud library and no streaming step between your files and the decks.

Licensing follows the same rule. It is designed around offline activation proofs: once a Mac is activated, the signed proof is stored locally and checked without contacting a server. An outage on our side should never interrupt your audio.

What you get from it

Most of this is invisible when it works, which is the point. What you should notice is what does not happen: loading a track does not interrupt the decks that are playing, a broken file fails its own import instead of the whole app, and a long set does not slowly change how Grit behaves.

Grit needs an Apple Silicon Mac with macOS 14 or later. It is in final testing and not on sale yet. The changelog follows the remaining work, and the download page has the requirements.

esc

120 BPM ↑↓ Select ↵ Launch