Duckling supports additive schema evolution with zero downtime. The Sequential Appender architecture automatically detects schema changes and handles them gracefully without requiring full re-syncs.
Adding new columns to MySQL tables is fully supported:
Automatic Detection: When you add a column to a MySQL table, Duckling automatically detects the new column during the next sync and adds it to the DuckDB schema.
-- MySQL: Add a new columnALTER TABLE users ADD COLUMN phone VARCHAR(20);-- Duckling: Automatically adds the column on next sync-- No manual intervention required
Behavior:
Existing rows in DuckDB will have NULL values for the new column
New syncs will populate the column with data from MySQL
New tables are automatically discovered and replicated:
-- MySQL: Create a new tableCREATE TABLE new_feature ( id INT PRIMARY KEY, name VARCHAR(255), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);-- Duckling: Automatically creates and syncs the table
How Table Discovery Works
On each sync cycle, Duckling queries MySQL for the list of tables
Column Drops Require Manual Cleanup: When you drop a column in MySQL, Duckling will not automatically drop it from DuckDB. The column remains in DuckDB with stale data.
Manual cleanup:
-- MySQL: Drop columnALTER TABLE users DROP COLUMN old_field;-- DuckDB: Manually drop column (optional)ALTER TABLE users DROP COLUMN old_field;
Alternatively, you can trigger a full re-sync to recreate the table with the new schema.
Primary Key Changes Not Supported: Adding or changing primary keys requires a full re-sync of the affected table.
Duckling relies on primary keys for:
INSERT OR REPLACE upsert logic
Deduplication in views
Data integrity
Recommended approach:
# 1. Stop synccurl -X POST http://localhost:3001/api/automation/stop# 2. Drop and recreate table in DuckDBcurl -X POST http://localhost:3001/api/query \ -d '{"sql": "DROP TABLE table_name"}'# 3. Full sync to recreate with new primary keycurl -X POST http://localhost:3001/api/sync/table/table_name# 4. Resume synccurl -X POST http://localhost:3001/api/automation/start
# Reset watermark for the tablecurl -X POST http://localhost:3001/api/query \ -d '{"sql": "DELETE FROM sync_log WHERE table_name = 'users'"}'# Trigger full sync to re-establish watermarkcurl -X POST http://localhost:3001/api/sync/table/users
Indexes Not Replicated: MySQL indexes are not replicated to DuckDB. DuckDB uses columnar storage and automatic indexing, so explicit indexes are rarely needed.
If you need indexes in DuckDB for specific query patterns:
-- Manually create index in DuckDBCREATE INDEX idx_users_email ON users(email);
Foreign Keys Not Enforced: Foreign key constraints from MySQL are not replicated to DuckDB. This is by design to avoid cascading failures during replication.
DuckDB tables are independent. If you need referential integrity checking:
-- Manually verify referential integritySELECT COUNT(*) FROM orders o LEFT JOIN users u ON o.user_id = u.idWHERE u.id IS NULL;
Unique constraints (except primary keys) are not enforced:
-- MySQL: Unique constraintALTER TABLE users ADD UNIQUE KEY unique_email (email);-- DuckDB: Not enforced-- Check manually if neededSELECT email, COUNT(*) FROM users GROUP BY email HAVING COUNT(*) > 1;
# Schema Changelog## 2025-03-01- Added `phone` column to `users` table- Created `user_preferences` table- Dropped `legacy_sessions` table## 2025-02-15- Changed `users.status` from VARCHAR to ENUM- Required full re-sync of users table
-- MySQL: Drop tableDROP TABLE new_feature;-- DuckDB: Drop table and clean sync logsDROP TABLE new_feature;DELETE FROM sync_log WHERE table_name = 'new_feature';
# Schema changes for specific databasecurl -X POST 'http://localhost:3001/api/sync/table/users?db=lms'# Verify schema for specific databasecurl 'http://localhost:3001/api/tables/users/schema?db=lms'