Merging Two Divergent Customer Tables
How a high-profile database merge between retail and CRM systems led to primary key conflicts, customer duplication, and broken dashboard metrics.
The Merging of Two Legacy Customer Databases
For years, the retail and e-commerce divisions operated as separate entities, maintaining their customer records in isolated systems. The retail team relied on an on-premise ERP database, while the digital marketing division managed online interactions using a modern cloud-based CRM. As part of a digital transformation strategy, the leadership ordered the consolidation of these two datasets into a single unified customer profile table. The goal was simple: create a complete overview of every client to drive personalized marketing campaigns. However, the technical execution of this plan revealed deep architectural conflicts. The retail database stored records with auto-incrementing integer primary keys, while the CRM system used UUIDs. This discrepancy was only the tip of the iceberg, as the true semantic conflicts lay in how each system identified a unique customer.
The Divergent Schema and the Overlapping Keys
The direct merge attempt introduced structural collisions that immediately corrupted data integrity. The integration script used a simple outer join on email addresses, but it failed to account for customers who used different emails for online and offline purchases. Furthermore, the retail database had thousands of legacy rows where the email field was empty or set to a placeholder, leading to a massive collision where thousands of offline profiles were merged under a single dummy profile. To make matters worse, the definition of an active customer differed fundamentally between systems. The retail database marked a customer as active if they had made a purchase within the last twenty-four months. In contrast, the CRM considered a user active if they had clicked an email link in the past thirty days. The initial script consolidated these flags by simply setting everyone to active, inflating the active customer count by over three hundred percent.
-- The migration query that merged tables on unsafe identifiers
INSERT INTO consolidated_customers (id, email, full_name, is_active)
SELECT
COALESCE(c.id, r.id + 1000000) AS id,
COALESCE(c.email, r.email) AS email,
COALESCE(c.name, r.name) AS full_name,
CASE
WHEN c.is_active = true OR r.last_purchase_date > NOW() - INTERVAL '2 years' THEN true
ELSE false
END AS is_active
FROM legacy_crm_customers c
FULL OUTER JOIN legacy_retail_customers r ON c.email = r.email;
Downstream Impact and the Rectification Plan
This schema merge immediately broke downstream financial and analytics reporting. Three critical dashboards that tracked customer retention, customer lifetime value, and active engagement metrics started displaying distorted numbers. Marketing campaigns were dispatched to outdated placeholder email addresses, resulting in a spike in bounce rates that damaged the email domain reputation. The database engineering team had to roll back the changes and establish a multi-stage consolidation pipeline. They introduced a deterministic matching engine that combined email, phone number, and physical mailing address to link accounts. They also designed a cross-reference routing table to keep legacy IDs mapped to the newly created UUIDs, ensuring that downstream systems could still query records without breaking dependencies. Finally, the team unified the semantic definition of 'active' into a composite score based on both purchase frequency and digital engagement.
- Implemented a deterministic customer matching algorithm utilizing phone number normalization and email parsing.
- Created a mapping schema to route legacy auto-incrementing integer IDs to consolidated UUIDs.
- Standardized the active user definition using a compound field based on recent purchase history and web portal logins.
Case Technical Specs
- Impact Level HIGH
- Target Engine PostgreSQL
- Complexity Advanced
- Category Cases
Discussion (0)
Post a Comment