Data Architecture and Migration Plan (Phase B/C)
This document defines data ownership in Phase B and the full migration strategy for Phase C.
Phase B: Data Ownership & Flow (No Content Migration)
- WordPress remains the single source of truth for content
- Laravel database introduced for new data only:
- Analytics (post views, unique views)
- User activities (views, bookmarks, shares)
- Device tokens (push notifications)
- User preferences
- Recommendations cache
- No duplication of WordPress content; Laravel references WordPress post IDs
Data Flow
Publish in WordPress → Webhook → Laravel: clear caches, trigger revalidate/build → Frontends fetch from Laravel API → Laravel caches & enriches → Return JSON to clients
Phase C: Full Migration Strategy
Scope
- Content migration: posts, pages, CPTs, taxonomies, users, comments, media, meta
- URL preservation with 301 redirects
- Editorial workflow migration and training
Phased Cutover (Zero Downtime)
1) Parallel Running (2-4 weeks)
- Laravel CMS up; editors test in real workflows
2) Dark Launch (1-2 weeks)
- 10% traffic to Laravel → monitor errors/SEO
3) Gradual Rollout (2-4 weeks)
- 25% → 50% → 75% → 100% traffic
4) Decommission WP (after 30 days stable)
- Final sync, keep backup for 90 days
Data Mapping: WordPress → Laravel
| WordPress | Laravel | Notes |
|---|---|---|
wp_posts |
posts |
type mapping, status mapping |
wp_postmeta |
post_meta/JSON cols |
normalize repeated meta |
wp_users |
users |
password rehash/migration strategy |
wp_terms/wp_term_taxonomy |
categories, tags |
maintain slugs and hierarchies |
wp_comments |
comments |
preserve threading and statuses |
| uploads/ | object storage (S3) + media table |
update URLs and sizes |
Example Laravel Adjunct Schema (Phase B)
CREATE TABLE user_activities (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT UNSIGNED NULL,
post_id BIGINT UNSIGNED NOT NULL,
activity_type ENUM('view','bookmark','share','comment') NOT NULL,
metadata JSON NULL,
ip_address VARCHAR(45) NULL,
user_agent TEXT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_user_post (user_id, post_id),
INDEX idx_post_activity (post_id, activity_type),
INDEX idx_created_at (created_at)
);
CREATE TABLE post_analytics (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
post_id BIGINT UNSIGNED NOT NULL UNIQUE,
view_count INT UNSIGNED DEFAULT 0,
unique_views INT UNSIGNED DEFAULT 0,
avg_read_time INT UNSIGNED NULL,
bounce_rate DECIMAL(5,2) NULL,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_view_count (view_count),
INDEX idx_updated_at (updated_at)
);
CREATE TABLE bookmarks (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT UNSIGNED NOT NULL,
post_id BIGINT UNSIGNED NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY unique_user_post (user_id, post_id)
);
Migration Tooling & Runbooks (Phase C)
- Artisan commands for orchestrated migrations with checkpointing
- Queue-based processing for large datasets
- Validation scripts to compare counts/hashes pre/post-migration
- Rollback procedures with DNS TTL set to 300s and verified backups
Example Commands
php artisan migrate:wordpress --type=posts --batch=1000 --dry-run
php artisan migrate:wordpress --type=posts --batch=1000 --validate
php artisan migrate:wordpress --type=posts --batch=1000 --execute
Rollback Plan
- Immediate: point DNS back to WordPress (low TTL)
- 1 hour: restore WP DB snapshot if needed
- 24 hours: post-mortem and remediation plan