Skip to content

Comparison & FAQ

Where super-line sits relative to the tools it's most often weighed against, and the questions that come up once you've read the model.

How it compares

super-lineSocket.IOtRPCraw ws
Typesafe contract⚠️ types-only
Runtime validation
Per-role contracts
Req/resack callbacks
Rooms
Topics (pub/sub)⚠️ via roomssubscriptions
Typed persisted collections
Durable background jobs & cron
Inter-server messaging
Domain plugins on the contract (auth · queue · chat · inspector)⚠️ routers only
Multi-node✅ adapter✅ adapter
Zero codegenn/a

Why not Socket.IO?

Socket.IO splits its types into ClientToServerEvents / ServerToClientEvents / InterServerEvents interfaces you maintain by hand and wire as positional genericsServer<C2S, S2C, …> on the server, reversed on the client, so swapping two still compiles. And its types are compile-time only: there's no runtime validation. super-line keeps the same directional split but in one shared object (can't misorder, can't drift), validates inbound automatically, and adds something Socket.IO doesn't have: per-role contracts — one server giving user and agent clients distinct, enforced surfaces. See Server-authoritative.

Why not tRPC?

tRPC is excellent for request/response (and SSE subscriptions), but it doesn't model rooms or client-driven pub/sub topics, and it's not built for bidirectional realtime. super-line is purpose-built for it while keeping tRPC-grade end-to-end types.

Why not a batteries-included backend (Firebase, Supabase)?

Those platforms hand you hosted batteries — auth, a database, realtime channels, scheduled functions — but the contract is theirs: loosely-typed rows and payloads, client-driven writes you claw back with a rules language, and your domain surface living somewhere else entirely. super-line's batteries are plugins that merge into your contract: plugin-auth (sessions, API keys, JWT), plugin-queue (durable jobs and cron), plugin-chat (channels, streaming AI messages, shared channel resources), and the Control Center inspector each contribute their collections and requests to the same typed, server-authoritative surface as your own handlers — self-hosted, one connection, no second SDK. See the plugin model and the plugin catalog.

Why not a distributed event emitter?

Redis pub/sub, a wrapped EventEmitter, NATS — reach for one when all you need is fan-out, and you get exactly that: bytes delivered to subscribers. What you don't get is everything super-line wraps around the fan-out — a shared contract, runtime validation of every inbound message, per-role surfaces, request/response correlation, and a server-authoritative authority that decides who may subscribe to what. super-line uses an emitter-shaped layer for this exact job — the pluggable adapter (Redis, libp2p, RabbitMQ, ZeroMQ) carries node↔node fan-out — but it is the typed, validated, authorized bus on top, not the raw pipe.

Why not BullMQ, pg-boss or Agenda?

Reach for a dedicated job runner when background work is the whole job — a batch pipeline with no realtime surface in front of it. plugin-queue exists for the other case: an app that already has a super-line contract and needs the slow half of a request to outlive the connection that asked for it. What it adds over a standalone runner is that the job is part of the same contract: input and result are Standard Schema entries validated like any other, so enqueue('sendEmail', …) infers and rejects at the same boundary as a request handler; jobs, schedules, and concurrency slots are ordinary collections in the same transaction domain as your rows, so a job and the row that caused it commit together; and the Control Center already sees them. What it deliberately doesn't add is a second datastore — no Redis instance, no separate worker deployment, no second dashboard.

The trade is scope. BullMQ has priorities, rate limiters, flows and a mature ecosystem; plugin-queue has retries, leases, per-queue concurrency, retention and cron, configured declaratively at construction and enforced by durable rows. If you need job primitives the plugin doesn't ship, use a dedicated runner — nothing about super-line stops you. See Queues and workers.

FAQ

Do I need Redis?

No. A single node uses the in-memory adapter. Add @super-line/adapter-redis — or any other adapter — only when you run more than one process. See Choose an adapter.

Do I need Redis for background jobs?

No — and the adapter isn't what makes queues work. Jobs, schedules and concurrency slots live in collections, so the collection backend decides how far they coordinate: memory or SQLite runs queues on one node, and a shared Postgres backend (@super-line/collections-pglite) makes claims, cancellation, cron and concurrency cluster-wide. An adapter only shortens the wake-up latency between a job landing and a node picking it up; durable polling stays the correctness path. See Run queues across a cluster.

Does the client work in the browser?

Yes (and Node 22+). It uses the global WebSocket; pass { WebSocket } on older runtimes.

How are types shared?

Put the contract in a module or package both sides import. No build step, no generated files — see The contract.

Can clients publish to topics?

No — topics are server-publish only. Send a request and have the handler publish. See Topics.

What's the delivery guarantee?

It depends on what is being delivered — the wire and the queue answer differently.

Messages on the wire are at-most-once. Offline clients miss events and topic pushes (no replay). Re-run join flows after reconnect and treat delivery as best-effort. See Reconnection & delivery.

Queue jobs are durable and at-least-once. An enqueued job is a persisted row; it survives a restart, is claimed under a lease, and is retried on failure or after a lease expires. That means a job can run twice — the external effect may land before completion is recorded — so workers must be idempotent and honor their AbortSignal. Use a job, not an event, whenever the work must not be lost.

In both cases the rule is the same: make handlers idempotent.

How do I document/teach this to an AI agent?

The repo ships an agent skill (SKILL.md + REFERENCE.md + RECIPES.md) that teaches AI coding agents the model and best practices. Copy it into your agent's skills directory, or see AI agents.

Is it stable?

Pre-1.0, but broad. Implemented: role-scoped contracts, request/response, events, rooms, topics, inter-server messaging, auth, reconnect, middleware, connection env (server-vended, client-visible per-connection state), plugins (inspector + auth + queue + chat), durable queues with cluster-wide cron, typed collections (last-writer-wins rows and CRDT documents) with the TanStack DB client engine, pluggable client↔server transports (WebSocket, HTTP, libp2p, loopback), pluggable server↔server adapters (in-memory, Redis, libp2p, RabbitMQ, ZeroMQ), and React hooks. Not yet: fire-and-forget signals, a NATS adapter, session resume/replay, and parameterized-topic type inference.

Released under the MIT License.