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