Shipeasy

Advanced use cases

Four cross-cutting patterns combining flags, configs, killswitches, metrics, alerts and feedback — the things you can only do when it is all one platform.

GuideOn this page · 6 min readWorks with · Whole platform · SDK · CLI · Admin API

Every primitive on its own is documented in its own section. This page is about the seams — the workflows that only exist because flags, configs, killswitches, metrics, alerts and feedback share one SDK, one API and one project. Each pattern below states the problem, the approach, and which primitives it wires together. Follow the links for the step-by-step version.

Roll a feature out to new tenants automatically

Problem. You're rolling a feature out tenant by tenant, but your tenant list is never static — new accounts sign up every day, and you don't want to redeploy or hand-edit a targeting rule each time one does.

Approach. Create one killswitch for the feature. A killswitch carries a map of named switches — per-key boolean overrides layered on top of the global state. Have your provisioning code call the Admin API to insert a tenant:<id> switch the moment a tenant is created, then flip that one switch to grant or revoke access — no code change, no deploy, one lever per tenant.

import { configure, Client } from "@shipeasy/sdk/server";

configure({ apiKey: process.env.SHIPEASY_SERVER_KEY! });

export async function handler(tenantId: string) {
  const flags = new Client({ user_id: tenantId });
  // resolves the tenant's named switch, falling back to the global state
  if (flags.getKillswitch("new-checkout", `tenant:${tenantId}`)) {
    return newCheckout(tenantId);
  }
  return legacyCheckout(tenantId);
}
# your onboarding job runs this as each tenant is provisioned
shipeasy release killswitch set new-checkout --switch-key tenant:acme --value true --env prod

Combines: killswitch switches + the Admin API driven from your own provisioning code.

Change plan entitlements without a redeploy

Problem. A customer upgrades, downgrades, or negotiates a custom limit, and you want the new entitlements — seat count, API quota, which features are unlocked — to take effect immediately, without shipping code or running a migration.

Approach. Model entitlements as a typed dynamic config rather than a flag. Store the limits and feature set as the config's value, and target it by a plan (or tenant) attribute. Your code reads one getConfig(); a plan change is a config edit — or just a change to the customer's attribute — applied through the dashboard, CLI or Admin API and live on the next poll.

const flags = new Client({ user_id, attributes: { plan: "business" } });
const limits = flags.getConfig("entitlements"); // { seats: 25, apiRpm: 600, export: true }

Combines: dynamic configs (typed values + targeting) + attributes + the Admin API for programmatic upgrades.

Ramp a feature that pages you when the number moves

Problem. You want to ramp a risky change from 1% to 100%, but not babysit a dashboard the whole time. If it drives error rate or latency the wrong way, it should stop — or at least page someone — before it reaches everyone.

Approach. Put the feature behind a gate and ramp its rollout percentage. Define the thing you're afraid of breaking as a metric, and attach a threshold alert to it — "checkout errors > 50 in the last hour". The alert is evaluated server-side by cron and files a ticket into your feedback queue the instant it breaches, while you keep the same feature's killswitch armed as the break-glass to cut it to zero without redeploying.

Combines: gate rollout + a metric + a threshold alert (auto-files a ticket) + a killswitch for break-glass.

Alerts need no SDK call

Alert rules are evaluated by a cron on the edge — you only define the rule and the metric. Nothing to poll, nothing to wire into the hot path.

Turn a spiking exception into an opened PR

Problem. A handled error that used to fire twice a day starts firing twice a minute after a deploy. You want it noticed, triaged and — where possible — fixed, without a human watching log volume.

Approach. Report the error through see() instead of a bare console.error, so it becomes a tracked error with a frequency the backend counts. Point a threshold alert at that error's rate; when it crosses the line the alert files a bug into the same ops queue as everything else. From there an AI trigger — Claude, Copilot, Cursor or Jules — picks the ticket up and opens a pull request against it. The loop from caught exception to proposed fix runs without anyone paging themselves.

Combines: see() error reporting → tracked-error frequency → a threshold alert (files the ticket) → the ops queue → an AI trigger that opens the PR.

Where to go next

These patterns are deliberately composed from primitives you can read about individually. If one is close to what you need, start from its section links above; if you want the smaller, single-primitive recipes, the Flags & Configs case studies are the next level down.

Was this page helpful?
Updated August 9, 2026✎ Edit this page

On this page