Frigate Inter-Process Communication System: How ZeroMQ Powers Real-Time Video Analytics

Frigate uses ZeroMQ (ØMQ) as its inter-process communication system, implementing a publish/subscribe pattern with a central proxy to route messages between detector workers, the core FastAPI server, WebSocket clients, and optional MQTT bridges.

Frigate is an open-source Network Video Recorder (NVR) with real-time object detection capabilities. To isolate CPU-intensive inference tasks from the web server while maintaining millisecond-level latency, the project implements a sophisticated inter-process communication system based on ZeroMQ sockets that enables asynchronous, non-blocking message passing between distributed components.

Architecture of the ZeroMQ IPC Layer

The communication backbone centers on a lightweight ZeroMQ proxy (frigate/comms/zmq_proxy.py) that brokers PUB/SUB traffic between isolated processes. Each component creates publisher or subscriber sockets using the zmq_ipc helper module (frigate/detectors/plugins/zmq_ipc.py), communicating over ipc:// transport endpoints.

This design decouples the detector workers (running TensorFlow or ONNX inference) from the core application (FastAPI server) and WebSocket broadcaster, preventing Global Interpreter Lock (GIL) contention while ensuring real-time event delivery.

Message Flow Between Components

The IPC system follows a strict message flow that guarantees delivery without blocking the inference pipeline:

  1. Detector workers publish detection events – After processing video frames, workers publish detection events, motion clips, and object-track data to a PUB socket connected to ipc:///tmp/frigate.ipc.

  2. The proxy routes messages – The central proxy receives messages on its frontend socket and immediately forwards them to its backend socket, acting as a message bus that decouples publishers from subscribers.

  3. The core consumes events – The FastAPI server subscribes to the backend socket to update the database, refresh the UI, and push real-time updates to WebSocket clients via frigate/comms/ws.py.

  4. External services receive broadcasts – Optional components like the MQTT bridge (frigate/mqtt/__init__.py) subscribe to the same backend socket to forward Frigate events to Home Assistant or other external systems.

Why Frigate Uses ZeroMQ for IPC

ZeroMQ provides specific advantages that make it ideal for Frigate's distributed architecture:

  • Low latency – The socket implementation is pure C with no heavyweight protocol parsing, enabling detection updates to reach the UI within milliseconds.

  • Scalable communication patterns – Built-in support for PUB/SUB, PUSH/PULL, and REQ/REP patterns allows Frigate to add new consumers (such as external analytics services) without modifying existing publisher code.

  • Transport agnostic – The same codebase works over ipc:// for same-host processes and tcp:// for distributed container setups, enabling flexibility in deployment topology.

  • GIL isolation – Because ZeroMQ sockets work between independent processes, each detector runs in its own Python interpreter, eliminating GIL contention between CPU-heavy inference and the web server.

Implementation Examples

Publishing Detection Events from Workers

Detector workers use the zmq_ipc helper to publish events via multipart messages with topic filtering:


# frigate/detectors/plugins/zmq_ipc.py

import zmq
import json

ctx = zmq.Context.instance()
pub = ctx.socket(zmq.PUB)
pub.connect("ipc:///tmp/frigate.ipc")

def publish_detection(event: dict) -> None:
    """Send a detection payload to the core."""
    payload = json.dumps(event).encode("utf8")
    # Topic "events" allows subscribers to filter efficiently

    pub.send_multipart([b"events", payload])

Subscribing to Events in the Core

The FastAPI core and WebSocket broadcaster subscribe to the backend socket to receive filtered events:


# frigate/comms/zmq_proxy.py - subscriber pattern

import zmq

ctx = zmq.Context.instance()
sub = ctx.socket(zmq.SUB)
sub.connect("ipc:///tmp/frigate.ipc")
sub.setsockopt(zmq.SUBSCRIBE, b"events")

while True:
    topic, payload = sub.recv_multipart()
    event = json.loads(payload)
    # Process event: store in DB, push to WebSocket, etc.

Starting the ZeroMQ Proxy

The proxy must run continuously to forward messages between frontend (publisher) and backend (subscriber) sockets:

python -m frigate.comms.zmq_proxy \
    --frontend="ipc:///tmp/frigate.ipc" \
    --backend="ipc:///tmp/frigate.backend.ipc"

The proxy binds the frontend socket where workers publish and the backend socket where the core subscribes, ensuring that late-joining subscribers immediately receive new messages without requiring message persistence or complex queue management.

Key Source Files

The IPC implementation spans several critical files in the blakeblackshear/frigate repository:

Summary

  • Frigate's inter-process communication system relies on ZeroMQ sockets to connect detector workers, the core server, and external services.
  • A central proxy (zmq_proxy.py) routes PUB/SUB messages over ipc:// transport, preventing GIL contention between inference and web serving.
  • The PUB/SUB pattern allows multiple consumers (WebSocket, MQTT, database) to receive detection events without impacting the publisher's performance.
  • ZeroMQ's transport-agnostic design enables Frigate to scale from single-process deployments to distributed container architectures using the same codebase.

Frequently Asked Questions

What inter-process communication system does Frigate use?

Frigate uses ZeroMQ (ØMQ) as its IPC mechanism, implementing a publish/subscribe pattern with a central message proxy that routes detection events between worker processes and the core application.

Why doesn't Frigate use MQTT for internal IPC?

While Frigate supports MQTT for external integration with home automation platforms, it uses ZeroMQ internally because ZeroMQ provides lower latency, more flexible socket patterns (PUB/SUB vs MQTT's broker model), and operates without requiring a separate broker service for internal process communication.

How does the proxy handle late-joining subscribers?

The ZeroMQ proxy guarantees that any subscriber connecting to the backend socket will immediately start receiving new messages published after the connection is established. This works without message persistence or complex queue management, ensuring the core application can restart without losing the ability to receive fresh detections.

Can Frigate components run on different physical machines?

Yes, because ZeroMQ is transport-agnostic. While the default configuration uses ipc:// sockets for same-host communication, changing the endpoints to tcp:// allows detector workers to run in separate containers or on different machines while using the same proxy architecture and code implementation.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →