db-sync-engine is a .NET worker service for ETL-style synchronization between databases. It reads data from a source table, normalizes values and schema for the target provider, creates or updates the target schema, and writes data in chunks.
The project is designed for recurring background sync jobs and stores sync progress separately in SQLite so runs can resume from the last processed key.
- syncs data between supported databases
- processes records in chunks
- tracks sync state in SQLite
- recreates or prepares target schema from source schema
- normalizes schema/types for the target database
- normalizes row values before writing
- removes duplicate rows inside a chunk by key before insert
- retries failed sync runs with exponential backoff
- supports running as a local .NET worker or in Docker
- MySQL
- PostgreSQL
- SQLite for sync process tracking
For each configured entity, the worker runs a full sync pipeline:
- load or create sync state
- ensure target schema exists and matches normalized source schema
- read a chunk from the source table ordered by key
- normalize row values
- deduplicate rows inside the chunk by key
- write the chunk to the target table
- update sync progress in SQLite
The worker repeats this in a background loop and waits IntervalSeconds between entity runs.
- Full sync strategy: current implemented sync mode is
Full - Chunked reads/writes: reads by key boundary and processes data in batches
- Resume support: stores
LastProcessedKeyand completion state in SQLite - Schema bootstrap: reads source schema, normalizes it for target DB, then applies it to the target
- Schema normalization options:
- preserve or lowercase names
- rename columns
- preserve default values
- set default varchar length
- optionally copy data during table replacement
- Write optimization:
- PostgreSQL writes use binary
COPY - MySQL writes use batched
INSERT
- PostgreSQL writes use binary
- Retry policy: failed entity runs are retried using exponential backoff
src/DbSyncEngine.Worker— host process and background loopsrc/DbSyncEngine.Application— sync strategies, pipeline, steps, optionssrc/DbSyncEngine.Infrastructure— DB connections, repositories, schema handling, normalizerssrc/DbSyncEngine.Domain— sync process state modelconfig/config.json— example runtime configurationdata/— SQLite state database when running locally or in Docker
The worker reads configuration from the path stored in the SYNC_CONFIG_PATH environment variable.
Example:
SYNC_CONFIG_PATH=/absolute/path/to/config/config.json{
"Sync": {
"Entities": [
{
"Name": "buffers",
"Target": {
"Provider": "MySQL",
"ConnectionString": "server=...;port=3306;database=...;User ID=...;password=...",
"Schema": "orders2",
"Table": "buffers"
},
"Source": {
"Provider": "PostgreSQL",
"ConnectionString": "Host=...;Database=...;Username=...;Password=...;",
"Schema": "orders",
"Table": "buffers",
"Columns": [],
"Key": "id",
"KeyType": "long"
},
"ChunkSize": 10000,
"InsertBatchSize": 1000,
"MaxInsertRetries": 3,
"IntervalSeconds": 2,
"Direction": "Full"
}
],
"SyncProcessDb": "Data Source=/app/data/sync_engine.db"
}
}Sync.Entities— list of sync jobsSync.SyncProcessDb— SQLite connection string used to store sync progress
Name— logical entity/job nameSource— source database connection and table settingsTarget— target database connection and table settingsChunkSize— number of rows to read/write per chunkInsertBatchSize— intended batch size setting in configMaxInsertRetries— retry count for failed entity runsIntervalSeconds— delay before the next run for this entityDirection— sync direction, currentlyFullNormalizerOptions— schema normalization options for target generation
Provider—MySQLorPostgreSQLConnectionString— database connection stringSchema— schema name when supported by the providerTable— table nameColumns— optional column whitelist; empty means all columnsKey— ordered key column used for incremental chunk boundariesKeyType— key type, supported values in code:long,int,datetime
- .NET SDK
- reachable source and target databases
- writable location for the SQLite sync state DB
dotnet restore src/db-sync-engine.sln
dotnet build src/db-sync-engine.slnSYNC_CONFIG_PATH=$(pwd)/config/config.json dotnet run --project src/DbSyncEngine.Worker/DbSyncEngine.Worker.csprojdotnet watch --project src/DbSyncEngine.Worker/DbSyncEngine.Worker.csproj runThe repository already includes Dockerfile and docker-compose.yml.
docker compose up --buildCurrent compose setup:
- mounts
./configto/app/configas read-only - mounts
./datato/app/data - sets
SYNC_CONFIG_PATH=/app/config/config.json
- sync progress is stored independently from source and target DBs
- the worker processes entities sequentially inside the background loop
- when no more rows are returned, the sync process is marked as completed
- PostgreSQL target writes use binary
COPYfor speed - MySQL target writes use multi-row
INSERT - duplicate rows inside a single chunk are reduced to the first row per key before writing
- unsupported providers throw
NotSupportedException - current implemented strategy is only
Full
Useful commands:
dotnet restore src/db-sync-engine.sln
dotnet build src/db-sync-engine.sln