migrationguides

How to migrate from Svix to HookSync in an afternoon

April 14, 2026 · 9 min read

Svix is a solid product. But at scale, a $0.000006 per message fee becomes significant — 10M events/month is $60. HookSync's Pro plan is $99/month for 5M events with no per-message fee. If you are sending more than 500k events/month and need the flexibility of self-hosting in the future, migration is worth the afternoon.

Step 1: Create your HookSync org and migrate endpoints

Export your Svix endpoints via their API. Each endpoint maps to a HookSync webhook endpoint — same URL, same event types.

# Create HookSync endpoint curl -X POST https://api.hooksync.net/api/v1/organizations/{org_id}/webhooks \ -H 'Authorization: Bearer {api_key}' \ -H 'Content-Type: application/json' \ -d '{ "name": "Fulfillment webhook", "url": "https://your-service.com/webhooks", "events": ["order.placed", "order.shipped"] }'

Step 2: Update signature verification

Svix uses svix-signature header with a different format. HookSync uses X-Webhook-Signature: sha256=<hex>. The HMAC-SHA256 algorithm is the same — only the header name and format differ.

// Before (Svix) const wh = new Webhook(secret); wh.verify(payload, headers); // After (HookSync) const sig = req.headers['x-webhook-signature']; const expected = 'sha256=' + crypto .createHmac('sha256', secret) .update(rawBody) .digest('hex'); crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));

Step 3: Migrate ingest calls

Svix takes events via their SDK. HookSync accepts a plain HTTP POST to /ingest/{org_id} with your API key in the Authorization header.

// Before (Svix) await svix.message.create(appId, { eventType: 'order.placed', payload: { orderId: '123' }, }); // After (HookSync) await fetch('https://api.hooksync.net/ingest/{org_id}', { method: 'POST', headers: { 'Authorization': 'Bearer {api_key}', 'Content-Type': 'application/json', }, body: JSON.stringify({ event_type: 'order.placed', payload: { orderId: '123' }, }), });

Step 4: Migrate consumer portal

If you use Svix's app portal (per-customer webhook management), HookSync has an equivalent: the consumer portal. You generate a short-lived portal token from your backend and pass it to your frontend or redirect the user to your portal UI.

// Generate token for consumer const { token } = await fetch( '/api/v1/organizations/{org_id}/consumers/{consumer_uid}/portal-token', { method: 'POST', headers: { Authorization: 'Bearer {api_key}' } } ).then(r => r.json()).then(r => r.data); // Consumer uses it directly against portal API // GET /portal/v1/organizations/{org_id}/endpoints // -H "Authorization: Bearer {token}"

Step 5: Cut over

Run both systems in parallel for 24h — send events to both Svix and HookSync and compare delivery logs. Once you are confident, remove the Svix call from your ingest code and cancel your Svix subscription.

← back to blog