The Merge.dev Migration Playbook: Moving to a Flexible Unified API Without Downtime
The complete runbook for evaluating Merge.dev alternatives and migrating to a flexible B2B SaaS integration platform with zero downtime and no re-auth.
If you are a senior product manager or engineering lead at a B2B SaaS company staring at a Merge.dev renewal quote and quietly running the numbers, this guide is for you. If you are evaluating a migration away from Merge.dev to a more flexible unified API, your biggest fear is likely the migration cliff. Forcing hundreds of enterprise users to click "Reconnect" on their Salesforce, Workday, or HubSpot integrations is a massive friction point. It generates support tickets, increases churn risk, and burns social capital with your best accounts.
The math on your current integration vendor might no longer make sense. The pricing structure might be dragging down your unit economics, or your enterprise customers are demanding custom field support that a rigid common data model simply cannot handle. You know you need to switch infrastructure, but you are paralyzed by the operational risk of asking every customer to re-authenticate.
The good news is that if you architected your initial implementation correctly—or even if you didn't, but are willing to put in specific operational work—there are concrete technical strategies to migrate OAuth tokens to a new unified API platform without touching your end users.
This is not theoretical. Teams do this every quarter. The reason it feels terrifying is that nobody writes down the runbook. We've documented similar playbooks for migrating beyond Finch, and the core principles remain the same. This guide breaks down the exact technical playbook to export OAuth tokens, import them into a generic credential context, handle rate limits post-migration, and use declarative mappings to mimic your old API responses so your frontend code does not have to change.
When to Migrate: A Decision Checklist
Before you commit engineering resources to a migration, pressure-test whether you actually need to move. Not every frustration with your current vendor justifies the operational cost of switching. Use this checklist to separate real architectural blockers from annoyances you can work around.
You should migrate if three or more of these are true:
- Your per-connection costs exceed 5% of the revenue generated by each integrated customer
- Enterprise deals are stalling because your integration layer cannot support custom fields or custom objects
- Your security or compliance team has flagged your vendor's sync-and-cache data storage during an audit (SOC 2, GDPR, or HIPAA)
- You are building workarounds - separate microservices, middleware, or background jobs - to compensate for limitations in the unified API
- Your vendor's integration roadmap does not align with the integrations your customers are requesting
- You need real-time data access but your vendor only supports scheduled syncs with stale data
- You own your OAuth applications (Client ID and Secret) in the third-party provider developer portals
- Adding a new integration requires waiting weeks or months for your vendor to build it
You should stay if:
- Your integration needs are stable, limited to standard fields, and your customer base is primarily SMB
- You are under 50 linked accounts and your current pricing is sustainable
- Your team lacks the engineering bandwidth to execute a phased migration over 4-8 weeks
- You do not own your OAuth apps, and forcing re-authentication across your customer base is not viable
The last point is a hard blocker. If your vendor owns the OAuth applications, there is no technical path to a zero-downtime migration. You would need to negotiate token export with your vendor or plan a customer re-authentication campaign. Verify OAuth app ownership before any other work.
The Merge.dev Migration Cliff: Why Teams Hesitate to Move
Migrating infrastructure is inherently risky. When that infrastructure handles the authentication and data synchronization for your customers' core systems of record, the perceived risk skyrockets. Product managers and engineering leaders often delay migrating off a legacy unified API because they assume the process requires a hard cutover.
A hard cutover means deprecating the old OAuth applications, spinning up new ones, and emailing every customer a guide on how to re-authorize your application in their CRM or HRIS. In a B2B environment, getting a system administrator to approve and execute a new OAuth grant can take weeks. During that window, data stops syncing. Workflows break. Customers complain.
But staying is worse. Integration sprawl on the customer side keeps growing. The average company now manages 305 SaaS applications, and organizations add roughly 12 new SaaS applications every 30 days, which compounds to 34% portfolio growth annually. Every one of those apps is another integration request that lands in your backlog.
Because of this fear, engineering teams often choose to stay on platforms that no longer serve their needs. They write brittle middleware to handle custom fields that the unified API drops. They build separate microservices to handle real-time webhook events because their vendor defaults to 24-hour polling. They accept that adding a new integration requires waiting for the vendor's roadmap.
A unified API vendor that cannot keep up with custom fields, custom objects, or weird per-tenant schemas is actively slowing your roadmap. Staying on a platform that limits your product velocity is a slow death for B2B SaaS. To move upmarket, you need infrastructure that adapts to your enterprise customers, not the other way around. The goal of the migration is not to just "swap vendors." The goal is to remove the bottleneck so your team ships integrations as fast as customers ask for them, without breaking what already works. You can avoid the migration cliff entirely by executing a zero-downtime token migration.
Evaluating Merge.dev Alternatives: What to Look For in a B2B SaaS Integration Platform
If the decision checklist confirms a migration, the next question is what to migrate to. The B2B SaaS integration platform landscape has matured, and Merge.dev alternatives fall into three architectural categories:
- Real-time unified APIs that proxy requests directly to the upstream provider without caching customer data
- Embedded iPaaS platforms that provide visual workflow builders and pre-built connectors
- Code-first integration frameworks where your engineering team writes and maintains integration logic as code
Each category optimizes for different trade-offs. For a detailed comparison of specific platforms in each category, see our Merge.dev alternatives guide. When evaluating any alternative, score each platform against these criteria:
| Criteria | Why It Matters |
|---|---|
| OAuth app ownership | Can you bring your own OAuth apps? If the platform owns the tokens, you are locked in again. |
| Data architecture | Does the platform cache your customers' data, or proxy in real-time? This determines your compliance posture. |
| Custom field support | Can you map custom fields per-account without code deploys? Enterprise deals depend on this. |
| Pricing model | Per-connection pricing penalizes growth. Look for per-integration, usage-based, or flat pricing. |
| Integration extensibility | Can you add or modify integrations yourself, or are you dependent on the vendor's roadmap? |
| Mapping overrides | Can you transform API responses to match your existing schema without changing your application code? |
The architectural difference between store-and-sync and real-time pass-through is the most consequential choice. Here is how the two patterns compare:
flowchart TB
subgraph sync["Store-and-Sync Architecture<br>(e.g., Merge.dev)"]
direction LR
A1[3rd Party API] -->|Scheduled Sync<br>every 1-24 hrs| B1[Vendor's<br>Database]
B1 -->|Cached Read| C1[Your App]
end
subgraph realtime["Real-Time Pass-Through Architecture<br>(Migration Target)"]
direction LR
A2[3rd Party API] -->|Live API Call| B2[Unified API<br>Proxy Layer]
B2 -->|Direct Response| C2[Your App]
end
style sync fill:#fff3e0,stroke:#e65100
style realtime fill:#e8f5e9,stroke:#2e7d32If you are moving from a store-and-sync platform to a real-time pass-through platform, your application may experience slightly higher latency (200-500ms per call) because data is fetched live instead of served from cache. Budget for this in your performance testing. The trade-off is that your data is always current, your compliance surface area shrinks, and you eliminate the "stale data" bugs that plague scheduled sync architectures.
Assessing the Vendor Lock-In: Pricing, Schemas, and Data Storage
Before you write a single line of migration code, do an honest audit of exactly which architectural constraints you are trying to escape. Vendor lock-in in the SaaS integration space typically manifests in three distinct ways: pricing penalties for growth, rigid data schemas, and compliance risks associated with data storage. Write these three down. They become the acceptance criteria for the new platform.
1. Punitive Pricing at Scale
Integration sprawl is a reality. As your customers connect more tools, your infrastructure costs should scale predictably. However, Merge.dev's pricing model can become prohibitively expensive at scale. Charging $650 per month for up to 10 linked accounts, and $65 for each additional account, creates a scenario where your integration infrastructure actively penalizes your growth. When your unit economics depend on adding 50 free-tier accounts for every paid account, a flat per-connection fee inverts your margin. The pricing model rewards your vendor for your customer's success, not yours.
2. The Trap of Rigid Common Models
Unified APIs promise a single data model for all integrations. This works perfectly for standard fields like first_name or email. But enterprise software runs on custom objects. Your largest customer might have 47 custom fields on the Salesforce Opportunity object. Your unified schema returns 12 of them. The remaining 35 require either a passthrough request, an unsupported workaround, or a contract upgrade. If your vendor forces all data through a rigid, pre-defined schema, those custom fields are either dropped or shoved into an unstructured metadata blob that requires custom code to parse. This is the single most common reason enterprise integrations stall in QA.
3. Sync-and-Cache Compliance Risks
Many legacy unified APIs rely on a sync-and-cache architecture. They pull data from third-party APIs, store it in their own databases, and serve it to you. This means your vendor is indefinitely storing your customers' PII (Personally Identifiable Information). If your vendor stores customer data to serve list endpoints quickly, you inherit their data retention posture during every security review. For compliance-strict industries like healthcare or finance, introducing a third-party database into the data flow complicates SOC 2, GDPR, and HIPAA audits. A real-time pass-through architecture, which does not store customer data at rest, is easier to defend than admitting "we cache 90 days of CRM data in a third party."
Quick Sanity Check: What is Vendor Lock-In in SaaS? Vendor lock-in occurs when systems rely on proprietary technologies or opaque authentication handling. In the API space, lock-in is often driven by who actually owns the OAuth Client ID and Secret. If you originally registered partner OAuth apps in Merge with your own Client ID and Secret, you can migrate tokens. If Merge owns the OAuth apps, you cannot. Most enterprise customers explicitly required "bring your own OAuth" during procurement, so this is usually fine—but verify in the dashboard before you commit to a date.
Pre-Migration Inventory and Risk Assessment
With your vendor lock-in audit complete, build a concrete inventory of everything that needs to move. Skip this step and you will discover edge cases in production.
Connected Accounts Inventory
Export a full list of linked accounts from your current vendor. For each account, document:
- Tenant ID: Your internal customer identifier
- Provider: The third-party system (Salesforce, HubSpot, Workday, etc.)
- OAuth app ownership: Do you own the Client ID and Secret, or does your vendor?
- Token status: Is the connection active, expired, or in an error state? Do not migrate broken connections.
- Last sync timestamp: When did this account last successfully sync data?
- Custom field usage: Does this customer use custom fields that your unified API currently supports (or fails to support)?
- API category: CRM, HRIS, ATS, accounting, etc.
Risk Classification
Classify each connected account into risk tiers:
| Tier | Criteria | Migration Strategy |
|---|---|---|
| Low risk | Standard fields only, low API volume, non-critical workflow | Migrate in first batch |
| Medium risk | Some custom fields, moderate API volume, important but not mission-critical | Migrate in second wave after validating low-risk accounts |
| High risk | Heavy custom field usage, high API volume, business-critical data sync | Migrate last, with dedicated QA and a tenant-specific rollback plan |
Data Reconciliation Baseline
Before migrating any tokens, capture a baseline snapshot from your current vendor for each connected account. This becomes your reconciliation reference:
// Capture baseline data from your current vendor for reconciliation
async function captureBaseline(tenantId: string, provider: string) {
const legacyContacts = await mergeSdk.crm.contacts.list({ accountId: tenantId });
const baseline = {
tenant_id: tenantId,
provider,
captured_at: new Date().toISOString(),
record_counts: {
contacts: legacyContacts.results.length,
total_pages: legacyContacts.next ? 'paginated' : 'single'
},
sample_records: legacyContacts.results.slice(0, 5).map(c => ({
remote_id: c.remote_id,
modified_at: c.modified_at,
field_keys: Object.keys(c)
}))
};
await db.reconciliation_baselines.insert(baseline);
return baseline;
}Store these baselines in your own database. After migration, you will run the same queries through the new platform and diff the results.
Sample Project Timeline
A typical Merge.dev migration for a team with 100-500 connected accounts follows this timeline. Simple migrations with well-documented source data and small volumes complete in 4 to 8 weeks. Complex migrations involving custom objects, multiple integrations, and compliance requirements routinely stretch to 12 months.
| Week | Phase | Key Activities |
|---|---|---|
| 1 | Audit & Planning | Export linked accounts, verify OAuth ownership, classify risk tiers, capture baselines |
| 2 | Platform Setup | Configure new platform, set up OAuth apps, write initial JSONata mappings |
| 3-4 | Shadow Testing | Import test tokens, run dual-read against internal accounts, fix mapping mismatches |
| 5-6 | Staged Rollout | Migrate low-risk accounts (10%), monitor for 48 hours, expand to medium-risk |
| 7 | Full Migration | Migrate remaining accounts including high-risk tier, with dedicated QA per tenant |
| 8 | Decommission | Verify 30 days of stable production traffic, decommission legacy connections |
Compress this for smaller deployments. Stretch it for regulated industries where each phase requires compliance sign-off.
The Zero-Downtime Strategy: Migrating OAuth Tokens
As we detailed in our step-by-step guide on migrating from Finch to a multi-category unified API, the entire premise of a zero-downtime migration rests on one technical requirement: you must own your OAuth applications.
If you registered your own OAuth apps in each provider's developer portal—like Salesforce or HubSpot—and configured them as "partner credentials" or custom apps in your current vendor, you hold the keys. The vendor is simply storing the access and refresh tokens on your behalf. Because you own the Client ID and Secret, you can export the active tokens from your current vendor and import them into a new platform. The third-party API does not know or care that the HTTP requests are originating from a different IP address, as long as the Bearer token matches the Client ID.
This is the part everyone gets wrong on the first attempt. The mechanics are not hard, but the sequencing matters.
Step 1: Export Tokens from Merge
Use the Merge Account Token endpoint to enumerate every linked account in scope. For each account, store the following in a temporary, encrypted staging table:
- The end customer identifier (your internal tenant ID)
- The provider name (salesforce, hubspot, etc.)
- The access token, refresh token, token expiry, and refresh token expiry
- Any provider-specific metadata you currently use (instance URL for Salesforce, hub ID for HubSpot)
Step 2: Import into a Generic Credential Context
A platform built on the interpreter pattern treats credentials as data. You POST the token blob into the new platform's integrated account endpoint, attach the same OAuth app (since you own the Client ID and Secret), and the platform takes over refresh from there.
// Pseudo-code: replay a token into a new integrated account context
await fetch('https://api.truto.one/integrated-account', {
method: 'POST',
headers: { Authorization: `Bearer ${TRUTO_API_KEY}` },
body: JSON.stringify({
integration: 'salesforce',
tenant_id: customer.tenant_id,
oauth_app_id: SALESFORCE_OAUTH_APP_ID,
credentials: {
access_token: merge.access_token,
refresh_token: merge.refresh_token,
expires_at: merge.expires_at,
instance_url: merge.metadata.instance_url
}
})
});When imported into a platform like Truto, the runtime engine takes over the token lifecycle. It proactively schedules work ahead of token expiry, utilizing the refresh token to acquire a new access token without any user intervention. Because the OAuth app is the same, the provider does not see a new consent event. From the customer's perspective, nothing changed.
Step 3: Verify Silently Before Cutover
Do not flip traffic yet. For each migrated account, fire a read-only call against the new platform and diff the response against the live Merge response. Log mismatches. Fix mappings. Repeat until the diff is empty. For deeper context on bringing your own OAuth, see our guide on OAuth App Ownership: How to Avoid Vendor Lock-In When Choosing a Unified API Provider.
Normalizing the Data: Mapping Responses to Match Your Old API
Migrating tokens solves the authentication problem. But if the new API platform returns data in a different JSON shape than Merge.dev, you will have to rewrite your entire frontend and backend data ingestion logic. The value of a declarative mapping layer shows up here. If you have to change your frontend code, the migration's cost balloons.
To achieve true zero downtime, the new API responses must exactly mimic the legacy schema you are migrating away from, on a per-account basis if needed. Most platforms cannot do this because they hardcode their integration logic. Truto takes a radically different approach: zero integration-specific code. The entire platform handles hundreds of integrations without a single if (provider === 'hubspot') statement in its runtime logic.
Integration behavior is defined entirely as data using JSONata—a functional query and transformation language for JSON. A JSONata expression is just a string, stored in the database, that says "given this input JSON, produce this output JSON." Expressions are versioned, hot-swappable, and overridable per environment or per account without a code deploy.
The 3-Level Override Hierarchy
To mimic legacy schemas and handle per-customer custom fields, you can utilize a three-level customization stack that deep-merges mapping modifications:
- Platform Base: The default unified mapping.
- Environment Override: A mapping override applied to your specific staging or production environment. You can write a JSONata expression here that reshapes all responses to match your old vendor's schema.
- Account Override: Individual connected accounts can have their own mapping overrides. If one specific enterprise customer has a highly customized Salesforce instance, you can override the mapping just for them.
flowchart LR A[Provider Response] --> B[Platform-level<br>JSONata mapping] B --> C[Environment override<br>deep-merged] C --> D[Account override<br>deep-merged] D --> E[Unified Response<br>matching old Merge shape]
Here is a contrived example. Merge returns CRM contacts in one shape; you want to emit Merge's exact shape from the new platform so your frontend stays untouched:
/*
Example JSONata expression to mimic a legacy unified API response.
This transforms the raw provider data into the exact schema your
frontend already consumes, extracting custom fields dynamically.
*/
{
"id": id,
"remote_id": properties.hs_object_id,
"first_name": properties.firstname,
"last_name": properties.lastname,
"email_addresses": [{
"email_address": properties.email,
"email_address_type": "WORK"
}],
"phone_numbers": properties.phone ? [{
"phone_number": properties.phone,
"phone_number_type": "WORK"
}] : [],
/* Extracting custom fields without writing custom code */
"custom_fields": properties.custom_enterprise_tier ? {
"enterprise_tier": properties.custom_enterprise_tier
} : null,
"last_activity_at": properties.notes_last_updated,
"remote_created_at": createdAt,
"modified_at": updatedAt
}By applying this mapping at the environment level, your application continues to receive the exact JSON structure it expects. You do not have to update your database schemas, your frontend components, or your background workers. When your largest customer has 35 custom fields on their Salesforce Opportunity, you do not want to add them to the global schema. Instead, apply an account-level override.
Read more about this architecture in our guide to 3-Level API Mapping: Per-Customer Data Model Overrides Without Code.
Handling Rate Limits Post-Migration
One of the most misunderstood aspects of unified APIs is how they handle rate limits. This is the section migration plans usually skip and then regret. A common marketing claim is that unified APIs "absorb" or "handle" rate limit errors for you. This is architecturally dishonest.
If you are making real-time pass-through requests to a third-party API and that API returns an HTTP 429 (Too Many Requests), a unified API cannot magically force the upstream provider to accept the request. Truto's stance is explicit and radically transparent: the platform does not retry, throttle, or apply backoff on rate limit errors. When an upstream API returns a 429, Truto passes that error directly back to the caller.
This is the right design. A unified API that silently retries on 429 will eventually mask a much worse failure: the provider has revoked your token, or your customer has hit their daily SOQL limit, and your sync is quietly dying in a retry loop. Surfacing 429 means your code stays in control.
What Truto does do is normalize the wildly inconsistent rate limit headers from hundreds of different providers into the standardized IETF specification:
ratelimit-limit: The maximum number of requests allowed in the current window.ratelimit-remaining: The number of requests remaining in the current window.ratelimit-reset: The time at which the rate limit window resets.
The IETF draft defines these to advertise quota policies and current service limits so clients can avoid being throttled. RateLimit-Limit is the quota for the time window, RateLimit-Remaining is the quota left in the current window, and RateLimit-Reset is the time remaining in the current window in seconds.
As you build your migration playbook, you must ensure your application logic is prepared to handle these standardized headers and implement its own exponential backoff with jitter. A minimal client-side handler looks like this:
// Example: Client-side exponential backoff handling standardized IETF headers
async function callWithBackoff(url: string, attempt = 0): Promise<Response> {
const res = await fetch(url, { headers: { Authorization: `Bearer ${TOKEN}` } });
if (res.status !== 429 || attempt >= 5) {
return res;
}
const reset = Number(res.headers.get('ratelimit-reset') ?? 1);
const jitter = Math.random() * 500;
const waitMs = (reset * 1000) + jitter;
console.warn(`Rate limited. Waiting ${waitMs}ms before retry.`);
await new Promise(r => setTimeout(r, waitMs));
return callWithBackoff(url, attempt + 1);
}Add a circuit breaker per tenant so one customer's runaway sync does not poison the queue for everyone else. For patterns, see API Rate Limit Best Practices.
Executing the Switch: The DNS Flip and Rollout Plan
The technical work is done. Now you sequence the cutover so a bad mapping in production does not cause a P1 incident. Because you have migrated the tokens and mapped the responses to match your existing schemas, you can execute the switch at the routing layer without dropping requests or webhooks.
The Non-Negotiable Rule: Never cut over more than 10% of tenants in the first 24 hours. The mappings that survive your test suite will still fail on real customer data. Budget for it.
Here is the step-by-step runbook for a zero-downtime rollout:
Step 1: Sandbox Parity Testing Create a sandbox environment in your new platform. Export a small batch of test tokens from your legacy provider and import them. Point your local development environment to the new API endpoints and verify that the JSONata mappings output the exact data shapes your application expects. Resolve every non-trivial difference at the mapping layer, not in your frontend.
Step 2: Shadow Traffic For 1-2 weeks, dual-write or dual-read in production for internal tenants only. Log diffs to a dashboard. Watch for slow drift on edge cases (deleted records, archived contacts, paginated cursors).
Step 3: Batch Token Migration Export your production OAuth tokens from the legacy vault and import them into Truto's credential context. Both platforms now hold valid access and refresh tokens. Move 5 tenants, watch error rates for 24 hours, move 20 more, repeat. Have a rollback path: keep the Merge tokens in your staging table until the new platform has been stable for 30 days.
Step 4: The Routing Flip
Update your API gateway or internal routing logic (via a feature flag) to direct requests for a specific subset of customer accounts to the new platform. Your API client should read from integrations.provider per tenant. Default new tenants to Truto on day one; flip existing tenants in waves.
sequenceDiagram
participant Client as Your Application
participant Gateway as API Gateway
participant Legacy as Legacy Unified API
participant Truto as Truto API
participant Provider as 3rd Party (e.g. Salesforce)
Note over Client, Provider: Phase 1: Pre-Migration (Legacy)
Client->>Gateway: GET /crm/contacts
Gateway->>Legacy: Forward Request
Legacy->>Provider: API Call (Token A)
Provider-->>Legacy: Raw Response
Legacy-->>Gateway: Mapped Response
Gateway-->>Client: Data
Note over Client, Provider: Phase 2: The Routing Flip<br>(Tokens migrated to Truto)
Client->>Gateway: GET /crm/contacts
Gateway->>Truto: Route flipped to new infrastructure
Truto->>Provider: API Call (Token A)
Provider-->>Truto: Raw Response
Truto->>Truto: JSONata Mapping (Mimics Legacy)
Truto-->>Gateway: Mapped Response
Gateway-->>Client: Data (Identical Shape)Step 5: Customer-Facing Communications A zero-downtime migration means your customers should not need to take any action. But your support and customer success teams need to be prepared. Before you flip traffic for any customer tier:
- Brief your support team on the migration timeline and what to watch for. Provide them with a one-page runbook of common issues (e.g., "data looks stale" means the mapping missed a field).
- Draft a proactive notification template for high-risk accounts. You may never send it, but having it reviewed and approved saves hours if something breaks at 2am.
- Update your internal status page with a maintenance window, even if no downtime is expected. This gives you cover for the small percentage of cases where latency spikes during cutover.
- Prepare a rollback communication plan. If you need to revert a tenant to the legacy platform, your customer success team should know the expected timeline and talking points.
The goal is not to broadcast the migration to customers. The goal is to be prepared to communicate if something goes wrong.
Step 6: Re-Point Webhooks Last If you rely on third-party webhooks, configure your new platform to ingest webhooks alongside your legacy provider. Inbound webhooks from providers are the most fragile part. Truto processes incoming webhooks, verifies signatures, and normalizes the payloads. Route these new webhooks to a staging endpoint on your server. Do not turn off the Merge webhook endpoint until you have seen 24 hours of normalized events flowing through the new pipeline.
Step 7: Decommission Merge Connections Only after the new platform has run all production traffic for 30 days should you formally decommission the old connections. Keep the OAuth app credentials intact; you own them, and you might need them again.
What to Watch During Cutover
- 429 response rates per integration: Should be near-zero if your client backoff is correct.
- Token refresh failure rates: Expect a small spike as the new platform takes over refresh.
- p95 latency per endpoint: Pass-through is typically slower than a cached API; budget 200-500ms more.
- Webhook event delivery counts: Compare before and after.
If any of these regress more than 2x baseline, pause the rollout and triage. The whole point of staging the migration in batches is that you can.
Post-Migration Validation and Monitoring Checklist
The routing flip is not the finish line. A migration is only complete when you have validated data integrity, confirmed performance baselines, and verified that no customer workflows are broken. Run this checklist for every migrated tenant.
Data Reconciliation
Compare the baseline snapshots you captured during the pre-migration inventory against live data from the new platform:
// Compare baseline against new platform data
async function reconcile(tenantId: string, provider: string) {
const baseline = await db.reconciliation_baselines.findOne({
tenant_id: tenantId, provider
});
const newContacts = await trutoSdk.crm.contacts.list({ tenantId });
const mismatches = [];
for (const sample of baseline.sample_records) {
const match = newContacts.results.find(c => c.remote_id === sample.remote_id);
if (!match) {
mismatches.push({ remote_id: sample.remote_id, issue: 'missing_record' });
} else {
const missingFields = sample.field_keys.filter(k => !(k in match));
if (missingFields.length > 0) {
mismatches.push({
remote_id: sample.remote_id,
issue: 'missing_fields',
fields: missingFields
});
}
}
}
return { tenant_id: tenantId, mismatch_count: mismatches.length, details: mismatches };
}Monitoring Checklist
Track these metrics daily for the first 30 days post-migration:
- Record count parity: Total records returned by the new platform should match the baseline within 2% (accounts for records created or deleted between captures)
- Field completeness: All fields present in baseline responses must appear in new platform responses. Missing fields indicate a mapping gap.
- Token refresh success rate: Should be >99.5%. Failures indicate an OAuth app configuration mismatch or a provider-side issue.
- API error rate per tenant: Track 4xx and 5xx responses. Any tenant with >1% error rate needs investigation.
- p95 response latency: Establish a new baseline. Real-time pass-through will be slower than cached reads - that is expected. Watch for degradation over time.
- Webhook delivery rate: If you migrated webhook endpoints, compare event counts before and after. Missing events indicate a routing or signature verification issue.
- Custom field accuracy: For high-risk tenants with custom field mappings, spot-check 10 records manually against the source system.
- Rate limit header presence: Verify that the new platform returns standardized rate limit headers for every provider. Your backoff logic depends on these.
Sign-Off Criteria
Do not decommission your legacy vendor connections until all of the following are true:
- All tenants have been migrated and running on the new platform for at least 30 days
- Token refresh has completed at least one full cycle for every connected account
- Data reconciliation shows less than 1% mismatch rate across all tenants
- No P1 or P2 incidents attributed to the migration in the last 14 days
- Your support team has not received migration-related tickets in the last 7 days
Strategic Wrap-Up
Migrating core integration infrastructure is a serious engineering undertaking, but it does not have to be a customer-facing crisis. A Merge.dev migration done right is unglamorous. No customer notices. No engineer pages at 3am. The runbook reduces to: own your OAuth, export tokens, replay into a declarative engine, mirror the response schema with JSONata, normalize rate limit headers, and cut over in waves.
The real value of migrating to a platform like Truto is not just escaping punitive pricing. It is adopting an architecture where integration-specific behavior is treated as data, not code. The payoff is what comes after the migration. Custom fields stop being a contract upgrade. New integrations stop being a six-week project. Per-account schema quirks stop being a reason to say no to enterprise deals. You move from managing a vendor to actually shipping integrations.
If you want a second set of eyes on your specific migration plan—especially the OAuth app ownership audit and the JSONata mapping strategy for your existing schema—we are happy to walk through it.
FAQ
- Can I migrate off Merge.dev without asking users to reconnect?
- Yes, provided you registered your own OAuth applications (Client ID and Client Secret) and configured them as partner credentials. You can export the active tokens and securely import them into your new infrastructure.
- What happens to my frontend code during a Merge.dev migration?
- If the new platform supports declarative response mapping (such as JSONata expressions), you can mirror Merge's exact response shape on a per-integration and even per-account basis. Your frontend code stays untouched.
- How do I handle custom fields during a Merge.dev migration?
- You can use declarative JSONata mappings to extract custom fields from the provider's raw response and map them to your exact required schema, bypassing rigid unified models through per-account overrides.
- How are rate limits handled after migrating off Merge.dev?
- Truto normalizes upstream rate limit information into standardized headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset) per the IETF spec. It passes HTTP 429 errors directly to the caller, meaning your service is responsible for implementing retry logic with exponential backoff.
- Will migrating API providers cause webhook downtime?
- No. By running both ingestion pipelines in parallel and migrating tokens in batches, you can flip the routing at the API gateway layer. Always run both for at least 24 hours before disabling the old endpoint to ensure zero dropped webhooks.