The Logical Case for Building Internally
The conversation usually starts in a partnerships or sales review. Migration friction keeps appearing as a reason deals slow down or customers stall during onboarding. Someone flags it as a pattern. Leadership asks what can be done.
Engineering is consulted. Their read is reasonable: yes, they can scope a migration tool. The platform's own API is well-documented. Import endpoints exist. The core work is data transformation: extract from Platform X, map to your schema, write to your system. That's a bounded engineering problem.
The logic holds. The project gets prioritized. Then it actually starts.
This article is about what happens next. Specifically, why the extraction side of that project consistently takes longer, costs more, and delivers less coverage than the initial scope suggested. Not because your engineering team isn't capable. Because the source platform problem is structurally harder than it looks, and the way internal builds are typically scoped misses the half that causes most of the trouble.
For context on why migration quality matters this much in the first place, The SaaS Onboarding Gap covers what customers switching platforms actually expect, and The Migration Bottleneck explains why the manual approach to closing that gap doesn't scale. This article focuses on the specific wall that internal tooling projects hit when they try to automate the extraction side.
The Part Your Team Gets Right
Writing migration data into your platform is genuinely manageable for an internal team. Your team wrote the destination API. You know the exact shape of every object your system accepts, which fields are required, and which validation rules will reject malformed input. When something breaks during import, your engineers can trace it to the source and fix it. Import endpoints, data validation layers, field mapping utilities: this work ships and produces real results.
This is the half of the problem that gets scoped accurately in the initial estimate. The argument here isn't that internal builds can't work. It's that they work well on this side and consistently struggle with the other.
The Source Platform Problem
Extraction is different in almost every way that matters.
The source platforms your customers are migrating from, whatever your competitive landscape looks like, are products you have no control over and no internal relationship with. In most cases, they are your direct competitors. They did not design their APIs with your migration use case in mind. Some have active reasons to make data extraction harder rather than easier.
Each source platform is its own independent integration project:
- Different authentication systems. Some use OAuth 2.0 with token refresh cycles that require active session management. Some use API keys with rotation requirements. Some have legacy authentication flows that behave differently across account types. Getting authentication right is not a one-time setup. It requires handling expiry, re-authentication, and edge cases in how each platform manages credentials.
- Different data models. The same concept (a group of users, a scheduled action, a rule-based trigger) is represented differently in every platform. Mapping these accurately requires deep knowledge of each source platform's schema at the field level, not just the object type. A field that represents one thing in Platform A maps to a structurally different concept in Platform B, with different behavioral implications on the destination side.
- Different rate limits. Some platforms rate-limit by requests per second. Some by daily call volume. Some by data transfer size. Some apply limits per endpoint rather than globally. Exceed them and extraction either fails silently or gets throttled in ways that are hard to detect from the outside. Managing rate limits across multiple source platforms requires separate queuing logic for each.
- Different pagination schemes. Cursor-based, offset-based, time-windowed, and platform-specific pagination each require their own implementation. Getting pagination wrong means either missing records silently or making redundant calls that count against rate limits.
- Different API maturity. Some platforms have well-versioned, consistently documented APIs. Others have a mix of current and legacy endpoints, undocumented parameters, and response fields that appear in some account tiers but not others. The behavior you test against in a standard account may not match what a high-volume customer's account returns.
Building extraction that handles even three source platforms correctly, not just the happy path but edge cases, partial failures, and account-type variations, is a multi-month engineering project. Building it across the ten or fifteen platforms a growing SaaS company realistically needs to support is a full product.
The write side of migration is a project. The read side is infrastructure. Most internal scopes treat both as projects.
What "Complete" Extraction Actually Requires
The deeper challenge is that not all customer data is accessible via API at all.
Source platforms have no particular incentive to expose everything through a programmatic interface. In practice, every major SaaS platform has assets and configurations that live in the product interface but aren't available through API calls. These aren't obscure edge cases. They're often the parts of a migration that customers care about most.
| Asset Type | API Accessible | Reality |
|---|---|---|
| Core records | Usually yes | Standard fields transfer. Custom fields require schema mapping. Relationship data between objects (contacts linked to accounts, tickets linked to customers, tasks linked to projects) often requires multiple linked API calls to reconstruct correctly. |
| Templates and assets | Partial | Some platforms return asset metadata via API but render the full content only in the interface. The working version of a template, report, or document layout may require browser-level access to retrieve completely. |
| Automation and workflow logic | Partial | Flow structure may be returned by the API, but conditional logic, branching rules, and timing configurations are sometimes stored in formats the API doesn't expose completely or returns in ways that require additional interpretation to reconstruct. |
| Account configurations | Often no | Permission structures, notification preferences, integration settings, and feature flags that affect platform behavior often exist only in the interface, not in any API endpoint. |
| Compliance and exclusion records | Variable | Records that govern who can be contacted or what actions are permitted. Some platforms expose these via API with correct pagination. Others require interface-level access or have export limitations that make bulk extraction unreliable. |
Getting complete coverage requires access at a layer below the API: reading the platform interface directly, the way a user would, through a browser. This is fundamentally different from API integration work. It requires maintaining browser session state, handling dynamic rendering, managing authentication in a browser context, and detecting interface changes that break extraction the same way an API deprecation would, except without a changelog or advance warning.
Internal teams that scope migration tooling typically scope the API work. The browser-level gap gets discovered mid-project, or post-launch when the first customer with a non-standard setup or an asset type that isn't API-accessible runs their migration and gets an incomplete result.
The Maintenance Problem Nobody Scopes
Even if you build complete extraction coverage across all your target source platforms, you've created an ongoing maintenance commitment with no natural endpoint.
Your own platform changes on a schedule you control. When you deprecate an API endpoint, you decide when and you write the migration guide. When you change your data model, your team knows it's coming. The maintenance burden of your own API is part of normal engineering operations.
Source platform maintenance is different:
- Authentication flows change. OAuth implementations get updated. API key formats change. Session handling behavior shifts. Any of these can break extraction for an entire source platform without a single line of your code changing.
- API endpoints get deprecated. Major platforms typically announce these with a window, but acting on deprecations competes with your actual product roadmap for engineering attention.
- Rate limits shift. Platforms adjust their API limits as their own systems grow. What worked reliably at your current migration volume may start failing under a more restrictive limit you weren't notified about.
- New features need coverage. When a source platform launches a new automation type or template format, customers will have assets built on that feature. If your extraction doesn't handle it, those assets don't transfer. Customers find out when their migration is "complete" but missing things they use every day.
- Interface changes break browser-level extraction. If you've built extraction that accesses the source platform interface directly, those integrations need updating whenever the interface changes, independent of API changes. There's no changelog for this. You find out when something stops working.
The maintenance scope that's almost never captured in the initial build estimate: your engineering team has taken on responsibility for staying current with your competitors' product changes. Every time a source platform updates, someone on your team needs to notice, diagnose whether it broke anything, and fix it before the next customer migration runs.
At low migration volume, this is manageable. A broken extraction gets noticed, diagnosed, and patched. At scale, when migrations are running regularly and customers are depending on the tooling, a broken extraction on a major source platform is an incident. Customer migrations stall. Support tickets spike. The engineering fix competes with everything else in the sprint.
Where Coverage Gaps Surface
A migration that covers 90% of a customer's data isn't 90% useful. It's as useful as its most critical gap allows.
A customer whose business depends on a specific re-engagement automation, say a flow that triggers on purchase behavior with conditional logic built over two years, and discovers that automation didn't transfer isn't 10% worse off. They're missing a core operational capability that drives revenue. The gap might represent 2% of their total data volume and a disproportionate share of their business logic.
Coverage gaps don't announce themselves at migration time. They surface days or weeks later, when a workflow that was supposed to run silently doesn't. The customer opens a support ticket. The issue traces back to an extraction gap in a data type or asset format your internal tool doesn't handle. The fix requires a partial re-migration or manual reconstruction, at exactly the moment the customer was supposed to be settled and seeing value from your platform.
Incomplete migrations don't fail at migration time. They fail later, when the customer discovers what didn't make it. By then, the goodwill from a smooth onboarding is already gone.
Coverage gaps also tend to surface in clusters: when you close a wave of competitive deals simultaneously, when you start winning customers from a new source platform, or when a source platform releases a new feature that customers rapidly adopt. These are the moments when extraction coverage is under the most pressure, and when gaps are most damaging to the high-value accounts you can least afford to lose.
The Build vs. Embed Decision
The question isn't whether your engineering team can build migration tooling. They can. The question is whether maintaining source platform integrations is the right long-term commitment for your engineering capacity.
If your competitive landscape is genuinely narrow (one or two source platforms account for the vast majority of your migrations), the build-internally case is stronger. You're maintaining a small number of integrations, the scope is bounded, and your team develops real expertise in those specific platforms. The calculus shifts when your source platform count grows, when customers start arriving from platforms you hadn't planned for, or when the maintenance burden starts consuming the bandwidth you need for core product work.
Two versions of the internal build decision play out in practice:
Version One: The Scoped Build
You build extraction coverage for your top two or three source platforms at the API level. It handles most migrations reasonably well. You launch it, migrations improve, and you manage the gaps with manual intervention when needed. The tooling stays in maintenance mode as a low-priority background system.
This is achievable. It delivers real value. It also leaves coverage gaps that surface on your most complex customers, doesn't handle assets that require browser-level extraction, and creates a maintenance backlog that grows as source platforms evolve and customers arrive from platforms you haven't built coverage for yet.
Version Two: The Full Coverage Build
You invest in complete extraction coverage across all relevant source platforms, including browser-level access for data that APIs don't expose. You staff the ongoing maintenance of those integrations. You build the operational infrastructure to detect and respond when a source platform change breaks extraction.
This is a product. It's not a quarter-long project. The team that owns it is the team that isn't building features on your core platform.
| Build Internally | Embed Purpose-Built Layer | |
|---|---|---|
| Write side (into your platform) | Your team owns this (correct) | Your team owns this (correct) |
| Read side (from source platforms) | Your team maintains competitor integrations | Offloaded to extraction infrastructure built for this purpose |
| API-inaccessible assets | Coverage gap or separate browser automation project | Handled through interface-level access |
| Source platform maintenance | Competes with product roadmap | Maintained by the migration layer |
| New source platform coverage | Engineering project each time | Expanded without consuming your roadmap |
Most internal builds start as Version One and get gradually pressured toward Version Two as customers discover gaps, partnerships requests new source platform coverage, and the maintenance backlog accumulates. The migration tooling that was scoped as a quarter project becomes a permanent infrastructure commitment that competes with your core product for engineering attention.
The embed decision isn't a concession that you can't build it. It's a recognition that your engineering team's time on source platform integrations has an opportunity cost. Every hour spent keeping a competitor's extraction current is an hour not spent on the product capabilities that make customers choose your platform in the first place.
Your team should own the destination. The extraction layer, the part that touches fifteen competitor platforms and needs to keep pace as each of them evolves, is the part that's built most efficiently by infrastructure that exists specifically for that purpose.
See what the extraction layer looks like in practice
We'll walk through how Beena handles source platform extraction, what we cover that APIs don't expose, and how that maps to your specific competitive landscape.
Book a callFrequently Asked Questions
Key Takeaways
The write side of migration is a project. The read side is infrastructure. Most internal builds scope the first and discover the second partway through.
- Writing migration data into your own platform is manageable for an internal team. You control the destination API, the data model, and the import logic. That part works.
- Extracting data from competitor platforms is fundamentally different. Each source platform has its own authentication system, data model, rate limits, and pagination behavior. Each is a separate integration project.
- Not all source platform data is accessible via API. Templates, automation logic, account configurations, and suppression records often require interface-level access to extract completely.
- Source platform maintenance is ongoing. Every API change, authentication update, or new feature at a competitor platform creates a corresponding update requirement for your extraction tooling, on a schedule you don't control.
- Coverage gaps surface on your most complex customers, at the worst possible moments. A migration that's technically complete but missing critical automation logic or template assets isn't a partial success. It's a support escalation and a churn risk.
- The build vs. embed decision isn't about capability. It's about where your engineering team's ongoing infrastructure commitment creates the most value: building your core product, or maintaining integrations with the platforms competing against it.
Every hour your engineers spend keeping a competitor's extraction current is an hour not spent on the product capabilities that make customers choose you in the first place. The build vs. embed decision comes down to whether that tradeoff is one you want to keep making as your migration volume grows.