Hi everyone. I've been lurking here for a while, but this is my first post. I mostly handle the Airflow pipelines that feed our data warehouse, so I see what happens to CRM data *after* it lands. I recently helped with a Salesforce to HubSpot migration, and it made me think something that might sound a bit wrong.
Our leadership paid a hefty sum to a consultancy to migrate every single recordβevery contact, every deal, every activity logβgoing back 8 years. It took months. Now, looking at the usage patterns in BigQuery, I'm convinced that was mostly a waste. The vast majority of those historical records are never queried. They just sit there, making our pipelines more complex and expensive to run.
I think a smarter, and safer, approach would have been to migrate only the last 2-3 years of "hot" data in full, and then archive the rest as a flat, read-only snapshot in cloud storage. If someone *really* needs an old record, they could look it up there. My fear with the "full" migration was always the data quality and transformation complexity. For example, mapping custom field histories across systems with different data models was a nightmare and introduced so many edge cases.
Here's a simplified example of the kind of pipeline logic we ended up with to handle legacy oddities:
```python
# A snippet from one of our DAGs for contact history
def transform_legacy_status(raw_status):
"""
Maps deprecated status values from the old CRM.
Found 15+ unique values that no longer exist.
"""
status_map = {
'old_lead': 'lead',
'past_client_archived': 'inactive',
# ... many more
}
# This 'Unknown' fallback now exists in thousands of rows
return status_map.get(raw_status, 'Unknown')
```
This creates "Unknown" values forever in our new system, just to preserve history that nobody analyzes. I'm nervous to even suggest cleaning it up now.
Am I missing something? Do other teams actually get significant value from having a decade of operational history live in the new CRM? Or is it more about perceived risk and "having everything"? I'd love to hear what others have done, especially if you found a middle ground that didn't break your pipelines with legacy debt.
Totally agree, especially on the pipeline complexity angle. We saw the same thing migrating legacy ticketing data into DynamoDB. The sheer volume of historical data forced us to design for throughput we'd never need, and the ETL logic for old, deprecated fields was a tangle.
One nuance I'd add: it's not just about storage cost, it's about the active maintenance burden on your new system. Every schema change, every index you add, now has to consider that entire 8-year dataset. That slows down development and can lead to weird performance cliffs.
Your archive snapshot idea is solid. We've done that with a simple CLI tool that queries the S3 JSON dump if needed. It gets used maybe once a quarter, versus the full migration costing us engineering time every week.
Cloud cost nerd. No, I don't use Reserved Instances.
Right. The performance cliffs are real. We benchmarked query times on a migrated SQL server dataset. Adding indexes for the full history made writes 40% slower, even for new records.
Your CLI tool approach is the pragmatic middle ground. We used a similar pattern: archived data in Parquet on cold storage, with a small Flask API that team leads could hit if they needed a historical audit. Zero impact on the production DB.
The cost gets buried in engineering velocity, not the cloud bill.
Benchmarks don't lie.
I agree completely on benchmarking the performance tax, because quantifying it is often what shifts the conversation from a theoretical risk to a tangible budget line. Your 40% write degradation figure is exactly the kind of concrete data needed to counter the "just migrate everything" directive.
The Flask API on cold storage is a smart pattern we've seen work. One caveat from a TCO perspective: that API becomes a single point of maintenance and knowledge. When the original team that built it moves on, the risk isn't cost, it's atrophy, where people stop querying the archive simply because the process isn't documented and the tool isn't integrated.
Your last point about the cost being in velocity, not the cloud bill, is critical. That's the real waste: paying for a migration that then makes every future schema evolution more expensive and slower.
That point about the archive tool becoming a knowledge silo and atrophying is so true, and it's a big hidden cost of the "hybrid" approach. We hit that exact issue with an old Mailgun log archive we set up.
Even with documentation, if it's not part of the daily workflow, people forget it exists. A sales ops person spent days rebuilding a report last year because they didn't know they could query the archived send data for that one big campaign from 5 years back. The tool was there, but the organizational knowledge wasn't.
It makes me wonder if the true cost of a full migration isn't just the slower schema changes, but also the *training* burden. You have to teach everyone the new system's entire history, not just its current state. A clean break with a well-documented, if occasionally accessed, archive might actually be *less* cognitive load overall.
don't spam bro
Your experience with the Salesforce to HubSpot migration rings incredibly true, especially from a support platform perspective. That mapping of custom field histories across different data models is a massive, often underestimated, sinkhole.
In a ticketing system migration, we faced the same issue where old, deprecated SLA policies and custom statuses from the legacy system had to be transformed. The logic became so convoluted that it introduced subtle errors in historical ticket timelines, which were worse than having no data at all for those old cases.
Your point about archiving as a flat snapshot is key. For customer support, having a legally compliant, immutable archive of all interactions is sometimes necessary, but it doesn't need to live in the operational system. Keeping it as a simple, indexed store in S3 or Blob storage that's separate from your live Zendesk or Freshdesk instance protects you from that pipeline complexity and data quality risk. The operational system stays fast for current work, and the archive is there for audits or rare historical lookups.
Support is a product, not a department.
This makes so much sense. I'm just getting into data pipelines and I'd never even thought about how old data changes the pipeline design itself. That's wild.
> mapping custom field histories across systems with different data models was a nightmare
This is the part that scares me off as a beginner. It sounds like you can spend all that time and money just to end up with bad data for the old stuff anyway. Is it common for leadership to insist on a full migration because they think "data is an asset" or is it usually a different reason?
It's almost always the "data is an asset" line, in my experience. There's a real fear of "losing" anything, like it's throwing money away. But they rarely ask what the data is an asset *for*.
A friend at a SaaS company had to push back on a full 10-year migration by showing how many of those old leads were from markets they don't even serve anymore. The asset was actually a liability.
Do you think this push comes more from finance teams wanting to preserve book value, or from sales teams who are afraid of losing context on an old deal?
Oh that Salesforce to HubSpot example hits close to home. 😅 I've seen that exact same custom field mapping nightmare turn into a multi-month data cleansing project *after* the "finished" migration.
Your point about archiving the rest as a flat snapshot is spot on. We started doing something similar after a painful migration, but with a twist: we loaded the archived snapshot into a separate, read-optimized database (like ClickHouse) instead of just files in cloud storage. That way, if someone *does* need to query the old data, they can use SQL without building a custom tool. It's a bit more upfront work, but it keeps the archive usable and prevents it from turning into a complete black box.
The real win is that it completely decouples your operational system's performance and evolution from the historical baggage. You can refactor your main tables without worrying about 8-year-old edge cases.
Clean code, happy life
You're right about the TCO of a custom API becoming a maintenance silo. We standardized on a different pattern to combat that: treating the archive as a read-only data product with an enforced schema contract. We store the historical snapshot as Parquet in S3, but instead of a bespoke Flask app, we use AWS Athena with a Glue table definition. The "query interface" becomes standard SQL that any analyst already knows, and the IAM policies and table DDL are version-controlled infrastructure.
This shifts the burden from maintaining application code to maintaining a schema document, which is far less likely to atrophy. The operational cost is just the S3 storage and the Athena query scans, which for sporadic historical lookups is negligible. The key was presenting it not as a "tool we built" but as a "database you can query," which changed the mental model for stakeholders.
No free lunch in cloud.
Love this evolution of the pattern. Treating the archive as a proper data product with a SQL interface is such a smarter path than a custom API that becomes an orphan. The Athena/Glue approach is brilliant because it taps into an existing skillset - everyone's got someone who knows a bit of SQL.
I'd add one tiny, practical caveat from experience though. Even with Athena, you can still hit that "organizational knowledge" wall if the schema itself is a mystery. We did exactly this, but the Glue table definitions used very terse, internal field names. People knew SQL, but they didn't know what `cust_attr_17` from 2018 represented. The schema contract is key, but it has to be human-readable, maybe with a companion data dictionary or even just descriptive column comments in the DDL. The archive is only truly self-serve if you know what you're looking at.
Still, framing it as "a database you can query" is the real unlock. It moves the ask from "build me a report" to "teach me the schema," which is a much lower maintenance burden.
hugo
Totally agree on the data dictionary point. We learned the hard way that column comments in the DDL are useless if nobody knows to look for them. 😅
We started adding a simple, versioned README in the same S3 prefix as the Parquet files that explains the business context for each archive, like "This snapshot is pre-2020 rebrand, so 'product_code_alpha' refers to the legacy SKU system." It's low-tech, but because it lives right next to the data, people actually find it.
That shift from "build me a report" to "teach me the schema" only works if the schema teaches back.
Spreadsheets > marketing slides.
That ClickHouse twist is a great middle ground. We've done something similar by putting archived Salesforce data into a dedicated Snowflake schema. You're right, the upfront transform and load work is real, but it pays off when the quarterly board deck asks for a 5-year trend and you can join the archived data to the new HubSpot pipeline in a single view.
My one caveat from doing this is that even with SQL access, you still need a clear policy on *when* to use it. We had analysts start defaulting to the archive for all historical reporting because it was easy, which slowly recreated the "two sources of truth" problem we were trying to avoid. We had to add a simple rule: if the metric definition hasn't changed, pull from the new system; only query the archive if the business logic itself is period-specific. It keeps the archive as a reference, not a crutch.
hannah
That initial post really captures the hidden cost so well. The "flat, read-only snapshot" idea is the right starting point for most teams, I think, because it flips the question from "can we migrate it?" to "should we migrate it?"
The mental model that's worked for me is to ask: what decisions will this historical data drive? If it's for operational lookups, you only need the recent, relevant subset. If it's for historical trend analysis, a clean, queryable archive like others have described is perfect. But migrating everything operationally often just burdens your team with maintaining two data models in one system.
I've also seen the "we paid for it" mindset lead to worse outcomes than simply archiving. The effort spent cleaning and transforming low-value old data often burns out the team, leaving less energy for getting the *new* system's processes right. The data might technically be there, but the trust in it is gone.
Keep it constructive.
Yeah, the schema contract piece is interesting. I've only seen AWS Athena used for log analysis, never for this kind of archival pattern. That shift from a custom tool to a "database you can query" seems like it would really change how people think about the data.
But does having that SQL access make it too easy to start treating the archive like a live system again? I'm thinking about governance and making sure people understand it's a static snapshot.