{"asOf":"2026-10-28","storesIpAddresses":false,"endpoint":"/api/swap","usage":"GET /api/swap?from={source}&to={target}","totalSwaps":15,"swaps":[{"id":"openai-to-openrouter","from":"openai","to":"openrouter","jtbd":"llm-router","wireCompatibility":"drop_in_base_url","estimatedMigrationMinutes":2,"oldPackages":["openai"],"newInstallCmd":"npm install openai@latest","envVarMapping":{"OPENAI_API_KEY":"OPENROUTER_API_KEY"},"codeDiffSnippet":"const client = new OpenAI({ baseURL: \"https://openrouter.ai/api/v1\", apiKey: process.env.OPENROUTER_API_KEY });","day2Gotchas":["Prefix model IDs with vendor namespace (e.g. openai/gpt-5, anthropic/claude-sonnet-4-5)."]},{"id":"sendgrid-to-resend","from":"sendgrid","to":"resend","jtbd":"transactional-email","wireCompatibility":"sdk_wrapper","estimatedMigrationMinutes":5,"oldPackages":["@sendgrid/mail"],"newInstallCmd":"npm uninstall @sendgrid/mail && npm install resend","envVarMapping":{"SENDGRID_API_KEY":"RESEND_API_KEY"},"codeDiffSnippet":"import { Resend } from \"resend\"; const resend = new Resend(process.env.RESEND_API_KEY); await resend.emails.send({ from, to, subject, html });","day2Gotchas":["Verify sending domain DNS (DKIM/SPF) in Resend before removing SendGrid records; default rate limit is 2 req/s (use /emails/batch for bursts)."]},{"id":"pinecone-to-qdrant","from":"pinecone","to":"qdrant","jtbd":"managed-vector","wireCompatibility":"schema_migration","estimatedMigrationMinutes":15,"oldPackages":["pinecone-client","@pinecone-database/pinecone"],"newInstallCmd":"npm install @qdrant/js-client-rest","envVarMapping":{"PINECONE_API_KEY":"QDRANT_API_KEY","PINECONE_INDEX_HOST":"QDRANT_URL"},"codeDiffSnippet":"import { QdrantClient } from \"@qdrant/js-client-rest\"; const qdrant = new QdrantClient({ url: process.env.QDRANT_URL, apiKey: process.env.QDRANT_API_KEY });","day2Gotchas":["Create payload indexes on metadata filter fields in Qdrant before querying at scale."]},{"id":"puppeteer-to-browserbase","from":"puppeteer","to":"browserbase","jtbd":"browser-automation","wireCompatibility":"drop_in_base_url","estimatedMigrationMinutes":5,"oldPackages":["puppeteer"],"newInstallCmd":"npm uninstall puppeteer && npm install playwright-core @browserbasehq/sdk","envVarMapping":{"CHROME_PATH":"BROWSERBASE_API_KEY"},"codeDiffSnippet":"const browser = await chromium.connectOverCDP(`wss://connect.browserbase.com?apiKey=${process.env.BROWSERBASE_API_KEY}`);","day2Gotchas":["Always call browser.close() in a finally{} block so remote sessions terminate immediately."]},{"id":"auth0-to-clerk","from":"auth0","to":"clerk","jtbd":"auth","wireCompatibility":"sdk_wrapper","estimatedMigrationMinutes":15,"oldPackages":["@auth0/nextjs-auth0"],"newInstallCmd":"npm install @clerk/nextjs","envVarMapping":{"AUTH0_SECRET":"CLERK_SECRET_KEY","AUTH0_CLIENT_ID":"NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY"},"codeDiffSnippet":"import { clerkMiddleware } from \"@clerk/nextjs/server\"; export default clerkMiddleware();","day2Gotchas":["Import existing user password hashes via Clerk Backend API migration endpoint to avoid forced password resets."]},{"id":"aws-rds-to-neon","from":"aws-rds","to":"neon","jtbd":"serverless-postgres","wireCompatibility":"drop_in_base_url","estimatedMigrationMinutes":10,"oldPackages":["pg"],"newInstallCmd":"npm install @neondatabase/serverless","envVarMapping":{"RDS_DATABASE_URL":"DATABASE_URL"},"codeDiffSnippet":"import { neon } from \"@neondatabase/serverless\"; const sql = neon(process.env.DATABASE_URL!);","day2Gotchas":["Use Neon's -pooler connection string for Prisma/Drizzle in serverless environments."]},{"id":"datadog-to-langfuse","from":"datadog","to":"langfuse","jtbd":"llm-observability","wireCompatibility":"sdk_wrapper","estimatedMigrationMinutes":5,"oldPackages":["dd-trace"],"newInstallCmd":"npm install langfuse","envVarMapping":{"DD_API_KEY":"LANGFUSE_SECRET_KEY"},"codeDiffSnippet":"import { Langfuse } from \"langfuse\"; const lf = new Langfuse(); const trace = lf.trace({ name: \"agent-run\" });","day2Gotchas":["Call await lf.flushAsync() before serverless handler exit."]},{"id":"langchain-to-vercel-ai-sdk","from":"langchain","to":"vercel-ai-sdk","jtbd":"agent-framework","wireCompatibility":"sdk_wrapper","estimatedMigrationMinutes":15,"oldPackages":["langchain"],"newInstallCmd":"npm install ai @ai-sdk/openai @ai-sdk/anthropic zod","envVarMapping":{"OPENAI_API_KEY":"OPENAI_API_KEY"},"codeDiffSnippet":"import { generateText } from \"ai\"; import { anthropic } from \"@ai-sdk/anthropic\"; const { text } = await generateText({ model: anthropic(\"claude-sonnet-4-5\"), prompt });","day2Gotchas":["Use maxSteps in generateText/streamText for bounded multi-step tool loops."]},{"id":"stripe-billing-to-polar","from":"stripe-billing","to":"polar","jtbd":"usage-based-billing","wireCompatibility":"sdk_wrapper","estimatedMigrationMinutes":10,"oldPackages":["stripe"],"newInstallCmd":"npm install @polar-sh/sdk","envVarMapping":{"STRIPE_SECRET_KEY":"POLAR_ACCESS_TOKEN"},"codeDiffSnippet":"import { Polar } from \"@polar-sh/sdk\"; const polar = new Polar({ accessToken: process.env.POLAR_ACCESS_TOKEN });","day2Gotchas":["Polar acts as Merchant of Record (handles global VAT/sales tax automatically)."]},{"id":"whisper-api-to-deepgram","from":"whisper-api","to":"deepgram","jtbd":"speech-to-text","wireCompatibility":"sdk_wrapper","estimatedMigrationMinutes":5,"oldPackages":["openai"],"newInstallCmd":"npm install @deepgram/sdk","envVarMapping":{"OPENAI_API_KEY":"DEEPGRAM_API_KEY"},"codeDiffSnippet":"import { createClient } from \"@deepgram/sdk\"; const dg = createClient(process.env.DEEPGRAM_API_KEY); const { result } = await dg.listen.prerecorded.transcribeUrl({ url }, { model: \"nova-3\" });","day2Gotchas":["Pass smart_format: true and diarize: true when transcribing multi-speaker meetings."]},{"id":"elevenlabs-to-cartesia","from":"elevenlabs","to":"cartesia","jtbd":"text-to-speech","wireCompatibility":"sdk_wrapper","estimatedMigrationMinutes":5,"oldPackages":["elevenlabs"],"newInstallCmd":"npm install @cartesia/cartesia-js","envVarMapping":{"ELEVENLABS_API_KEY":"CARTESIA_API_KEY"},"codeDiffSnippet":"import { CartesiaClient } from \"@cartesia/cartesia-js\"; const client = new CartesiaClient({ apiKey: process.env.CARTESIA_API_KEY });","day2Gotchas":["Use Sonic WebSocket streaming for sub-100ms first-audio-byte latency."]},{"id":"algolia-to-typesense","from":"algolia","to":"typesense","jtbd":"search-engine","wireCompatibility":"schema_migration","estimatedMigrationMinutes":15,"oldPackages":["algoliasearch"],"newInstallCmd":"npm install typesense","envVarMapping":{"ALGOLIA_API_KEY":"TYPESENSE_API_KEY"},"codeDiffSnippet":"import Typesense from \"typesense\"; const client = new Typesense.Client({ nodes: [{ host, port: 443, protocol: \"https\" }], apiKey: process.env.TYPESENSE_API_KEY! });","day2Gotchas":["Define explicit facet: true fields in your Typesense collection schema."]},{"id":"celery-to-inngest","from":"celery","to":"inngest","jtbd":"durable-execution","wireCompatibility":"sdk_wrapper","estimatedMigrationMinutes":15,"oldPackages":["bull","celery"],"newInstallCmd":"npm install inngest","envVarMapping":{"REDIS_URL":"INNGEST_EVENT_KEY"},"codeDiffSnippet":"import { Inngest } from \"inngest\"; export const inngest = new Inngest({ id: \"agent-app\" });","day2Gotchas":["Wrap each non-idempotent LLM or side-effect call inside step.run() so retries replay deterministically."]},{"id":"aws-s3-to-cloudflare-r2","from":"s3","to":"r2","jtbd":"object-storage","wireCompatibility":"drop_in_base_url","estimatedMigrationMinutes":3,"oldPackages":["@aws-sdk/client-s3"],"newInstallCmd":"npm install @aws-sdk/client-s3","envVarMapping":{"AWS_ACCESS_KEY_ID":"R2_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY":"R2_SECRET_ACCESS_KEY"},"codeDiffSnippet":"const s3 = new S3Client({ region: \"auto\", endpoint: `https://${process.env.CF_ACCOUNT_ID}.r2.cloudflarestorage.com`, credentials: { accessKeyId: process.env.R2_ACCESS_KEY_ID!, secretAccessKey: process.env.R2_SECRET_ACCESS_KEY! } });","day2Gotchas":["Never npm install r2 (deprecated 2017 HTTP wrapper); use @aws-sdk/client-s3 with R2 endpoint for $0 egress."]},{"id":"smithery-to-mcp-registry","from":"smithery","to":"mcp-registry","jtbd":"mcp-discovery","wireCompatibility":"drop_in_base_url","estimatedMigrationMinutes":3,"oldPackages":["@smithery/cli","@smithery/sdk"],"newInstallCmd":"npm uninstall @smithery/cli @smithery/sdk && npm install @modelcontextprotocol/sdk","envVarMapping":{"SMITHERY_API_KEY":"NONE_REQUIRED"},"codeDiffSnippet":"// Connect directly to remote Streamable-HTTP MCP server URLs discovered via https://registry.modelcontextprotocol.io or /.well-known/mcp/server.json","day2Gotchas":["Smithery Connect proxy (server.smithery.ai / run.tools) shuts down October 31, 2026."]}]}