Shoal separates deploying code from releasing it. You merge features behind a flag, ship them to production switched off, and turn them on for a teammate, a beta cohort or 5% of traffic — without another deploy.
How it works
Your app talks to Shoal through a small SDK. On start-up the SDK downloads the ruleset for its environment — a compact JSON document describing every flag — and evaluates flags locally. Evaluation never waits on the network, so a flag check costs microseconds.
import { createClient } from "@shoal/sdk";
const shoal = createClient({ key: process.env.SHOAL_KEY! });
if (await shoal.isOn("new-checkout", { user: { id: "u_42", plan: "pro" } })) {
renderNewCheckout();
}When someone changes a flag in the dashboard, connected SDKs receive the update over a streaming connection within about a second.
Why Shoal
- Typed flags.
shoal generatewrites a TypeScript union of your flag keys, so a typo is a compile error, not a silentfalse. - Local evaluation. No per-request network calls, no latency budget, works offline from the last known ruleset.
- Edge-ready. The SDK runs in Node, Bun, Deno, browsers and edge runtimes with zero dependencies.
- Audit everything. Every change records who, what and why, and can be reverted from the history view.