Skip to main content

Overview

The @shipdit/convex component keeps the last valid shipd snapshot in Convex. Your queries read that local copy, so flag evaluation stays reactive and does not add a network request to each function call. The integration is available on every shipd plan. Mount one named component instance per shipd environment. For example, mount shipdDevelopment and shipdProduction separately. Each instance has its own SDK key, signing secret, snapshot, and health status.

Install

Add the component to convex/convex.config.ts. The httpPrefix gives each instance a distinct webhook route.
convex/convex.config.ts
Run npx convex dev after changing component mounts so Convex regenerates components.

Configure environment values

Set these values for every mounted instance:
The component fetches snapshots from https://edge.useshipd.com. Do not expose the SDK key or webhook secret to browser code.

Create the webhook destination

  1. Open the project in the shipd dashboard and go to Settings → Integrations.
  2. Under Convex, choose the matching environment.
  3. Enter https://<your-deployment>.convex.site/shipd/production/webhook.
  4. Click Create destination.
  5. Copy the signing secret immediately and replace SHIPD_PRODUCTION_WEBHOOK_SECRET in Convex.
  6. Redeploy, then click Test delivery.
The callback hostname must end in .convex.site and use HTTPS. shipd signs the exact request body and sends only publication metadata. The component fetches the canonical snapshot from the edge; the webhook never contains flags or credentials.

Wrap host queries

Create one wrapper for each mounted instance. Defaults are required and stay type-safe.
convex/lib/shipd.ts
Component functions cannot see your host application’s ctx.auth. Authorize in the host function before calling the wrapper:
convex/checkout.ts
The wrapper also provides getNumber, getJson, and evaluate. Use evaluate when you need the reason, matched rule, snapshot version, or stale state.

Inspect sync health

Call getStatus from an authorized host query:
hasSnapshot tells you whether an initial sync succeeded. version, etag, and fetchedAt identify the cached snapshot. lastAttemptAt, lastError, and lastErrorAt describe sync health. stale: true means a valid cached snapshot exists but the latest refresh failed. Webhooks provide fast invalidation. A one-minute ETag poll is the reliability fallback. You can also call syncNow from an authorized host action.

Understand defaults and stale snapshots

  • Before the first valid snapshot, the wrapper returns your typed default.
  • A missing flag or value-type mismatch also returns its typed default.
  • After a successful sync, the component keeps the last valid snapshot indefinitely.
  • A refresh failure marks that snapshot stale but does not replace it with defaults.
  • Older out-of-order snapshots are ignored.
This makes temporary shipd, webhook, or network failures fail stable instead of changing flag behavior.

Rotate credentials

Rotate the webhook secret without creating a second destination:
  1. In the project’s Settings → Integrations, choose the environment, then click Rotate secret.
  2. Copy the new secret immediately.
  3. Update the matching SHIPD_WEBHOOK_SECRET value in Convex and redeploy.
  4. Click Test delivery.
There is no overlap window: requests signed with the old secret fail after rotation. Coordinate the dashboard rotation and Convex deployment during a short maintenance window. The one-minute poll continues refreshing snapshots if webhook delivery fails. Rotate the SDK key separately by creating a replacement server SDK key for the same environment in SDK keys, updating SHIPD_SDK_KEY, confirming a successful sync, and then revoking the old key.

Next