How-To Guide

Multi-Target Jobs & BACPAC Seed

Step-by-step visual walkthrough: migrate one database to multiple servers simultaneously using the Jobs tab, and handle very large tables (≥0.5 TB) using BACPAC seeding via SqlPackage.

The Jobs tab runs each job in its own background thread — not sequentially. All jobs start at the same time (up to the concurrency limit you set). Each job maintains a completely independent connection, progress bar, and log. One source database can fan out to 3, 5, or 10 different target servers in a single click.

Architecture — Source → Multiple Targets (parallel threads)
🗄
Source Server
Azure SQL / SQL Server
source database
AWS RDS
Job #1
Thread 1
Azure SQL DB
Job #2
Thread 2
🖥
On-Prem VM
Job #3
Thread 3

All three jobs read from the same source simultaneously — each writes to its own target server — wall-clock time = slowest single job, not sum of all.

Follow these steps in order. Each step shows exactly what the screen looks like at that point.

1
Open the DB Migration window & configure Step 5 (connections)
Before using Jobs, the main source and target connections on Step 5 must be filled in. The Jobs tab uses these as the default source and target. Individual jobs can override the target server — but the source host, port, and credentials always come from Step 5.
Required fields in Step 5: Source type, host, port, username, password. Target type, host, port, username, password. At minimum, the source side must be complete.
2
Click the Jobs tab
The Jobs tab is the last tab across the top of the DB Migration window.
DB Migration Window — Tab Bar
DB Migration
Schema Objects
Comparison
Run
Jobs ← click here
Jobs tab content appears here after clicking
3
Set the Concurrency level
The Concurrency spinner (next to "+ Add Job") controls how many jobs run at the same time. Each running job opens its own database connections and reads from the source simultaneously.
Jobs Tab — Toolbar
+ Add Job
Concurrency:
3
Run All
Stop
Export Combined Report

↑ Set concurrency to 3 here: all 3 jobs start at once. Set it to 1 to run them sequentially (useful if the source DB is under load).

Recommended concurrency: 2–3 for production sources. Each job opens its own connection pool and reads from the source concurrently — high concurrency adds I/O load on the source server. For AWS RDS sources with General Purpose SSD (gp2/gp3), start with 2.
4
Click + Add Job for each target
Each click adds one job row. You need one row per target server (or per database if sending the same DB to multiple targets). Fill in the Source DB name and Target DB name.
Jobs Tab — Three jobs added, before Override Target is configured
#1
Source DB:
salesdb
Target DB:
salesdb
□ Override target
Pending
Show log ▾
#2
Source DB:
salesdb
Target DB:
salesdb
□ Override target
Pending
Show log ▾
#3
Source DB:
salesdb
Target DB:
salesdb
□ Override target
Pending
Show log ▾

↑ All three jobs show the same "salesdb" source → "salesdb" target. Without Override Target checked, all three would go to the SAME target server (Step 5 default). See Part 2 below to point each job to a different server.

By default every job uses the target server from Step 5. To send a specific job to a different server (AWS RDS, Azure SQL, on-prem VM, etc.), check "Override target" and load a saved connection profile. Here is exactly how to do it.

A
First — save a connection profile for each target server
Go to Step 5 → Connections, fill in the target server details, then click Save Profile. Give it a descriptive name like AWS-RDS-us-east-1 or AzureSQL-DR. You only do this once per server.
Step 5 — Save a connection profile (do this for EACH target server)
DB Type
SQL Server
Host
mydb.abc123.us-east-1.rds.amazonaws.com
Port
1433
Username
admin
Password
••••••••
Profile name
AWS-RDS-us-east-1
Save Profile

↑ Fill host, port, credentials → type a profile name → click Save Profile. Repeat for every target server (AWS RDS, Azure SQL DR, on-prem VM, etc.)

Important: The profile name is what you'll pick in the Jobs tab Override Target dropdown. Use a clear name — you cannot see the host inside the dropdown, only the profile name.
B
In the Jobs tab — check "Override target" on the job
Find the job row you want to redirect to a different server. Check the Override target checkbox on that row. A second row expands below showing a Target profile dropdown and a Load button.
Jobs Tab — Job #1 with "Override target" checked → profile row expanded
#1
Source DB:
salesdb
Target DB:
salesdb_rds
Override target
Pending
⟳ Target profile:
AWS-RDS-us-east-1
Load
SQL Server @ mydb.abc123.us-east-1.rds.amazonaws.com:1433
Show log ▾
What each field does:
Target DB field (top row, right of "→") — the database name to create/use on the target server. Can be different from the source DB name.
Target profile dropdown (expanded row) — pick the saved profile for the target server.
Load button — applies the profile (host, port, credentials) to this job. The server address summary appears to the right of the button after loading.
C
Select the profile from the dropdown and click Load
Click the dropdown to see all saved profiles. Select the one for this job's target server. Then click Load. The server summary (type @ host:port) will appear immediately to the right of the Load button, confirming the override is active.
Three jobs — each directed to a different server
#1
Source DB:
salesdb
Target DB:
salesdb
Override target
Pending
Target profile:
AWS-RDS-us-east-1
Load
SQL Server @ mydb.rds.amazonaws.com:1433 ✓
#2
Source DB:
salesdb
Target DB:
salesdb
Override target
Pending
Target profile:
AzureSQL-DR
Load
Azure SQL DB @ contoso.database.windows.net:1433 ✓
#3
Source DB:
salesdb
Target DB:
salesdb
Override target
Pending
Target profile:
OnPrem-VM-SQL2022
Load
SQL Server @ 10.0.1.45:1433 ✓

↑ All three jobs use the same source DB "salesdb" but each overrides the target to a different server. Concurrency = 3 means they all run simultaneously.

D
Click Run All — watch all jobs execute in parallel
After clicking Run All, all jobs change status from Pending to Running simultaneously. Each progress bar advances independently. Click Show log ▾ on any job row to see its live migration log.
Jobs Tab — All three jobs running concurrently
#1
salesdb → salesdb @ AWS-RDS-us-east-1
Running
62% Copying dbo.OrderLine (1,248,000 / 2,010,000 rows) — 14,200 rows/s
#2
salesdb → salesdb @ AzureSQL-DR
Running
41% Copying dbo.Customer (820,000 / 2,010,000 rows) — 9,800 rows/s
#3
salesdb → salesdb @ OnPrem-VM-SQL2022
Done ✓
✓ Completed in 4m 12s — 2,010,000 rows — all tables OK
E
Export the Combined Report after all jobs finish
When all jobs complete, the Export Combined Report button activates. Click it to save a single HTML file showing row counts, timing, and pass/fail status for every table across all jobs — useful for sign-off documentation.
The combined report is the official migration record — it shows every table, every job, row count matched or mismatch, and total elapsed time. Save it as combined_migration_report.html and attach it to your change ticket or DR runbook.

The standard row-copy engine is efficient up to a few hundred GB. For tables that are 500 GB or larger (Audit log tables, historical fact tables, large JSON blob columns), it is faster and safer to use BACPAC export via SqlPackage combined with a bulk-load import. The tool handles this automatically with the BACPAC Seed button.

BACPAC Seed requires Azure SQL Database as the source. The import strategy differs depending on your target — read the correct path below before starting.
Target Export Import method Supported by tool?
Azure SQL Database SqlPackage /Action:Export → .bacpac bcp.exe bulk-load (2-part name + -d flag) ✅ Built-in — use the Seed button
AWS RDS for SQL Server SqlPackage /Action:Export → .bacpac Manual — S3 + native restore (see below) ⛔ Not automated — manual steps required

Path A — Azure SQL Database → Azure SQL Database

BACPAC Seed — Three-Step Pipeline per Table (Azure → Azure)
🗄
Step 1/3
SqlPackage Export
Azure SQL → .bacpac
on local disk
💾
Step 2/3
bcp.exe bulk-load
.bacpac → Azure SQL
target database
🔄
Step 3/3 (optional)
CDC Catch-Up
rows written during
export/import window

Tables are processed sequentially to avoid overloading local disk with multiple large .bacpac files.

Why bcp.exe instead of SqlPackage /Action:Import?
SqlPackage /Action:Import requires a completely empty target database (it will error SQL71659 if any schema or data exists). Since your target already has schema deployed and other tables migrated by the standard engine, import would fail. Instead the tool extracts the BCP data files from inside the .bacpac ZIP and bulk-loads them directly with bcp.exe — this inserts rows into an existing table without touching anything else.

Azure SQL note: bcp on Azure SQL requires a two-part name (schema.table) plus the -d database flag. The three-part name (database.schema.table) that works on on-prem SQL Server is rejected by Azure SQL with Invalid object name (NativeError 208). The tool handles this automatically.
Pre-requisite — SqlPackage.exe must be installed.
# Option 1 — install via dotnet CLI (recommended): dotnet tool install --global microsoft.sqlpackage # Option 2 — already installed with SSMS at: C:\Program Files\Microsoft SQL Server\160\DAC\bin\SqlPackage.exe C:\Program Files\Microsoft SQL Server\150\DAC\bin\SqlPackage.exe
bcp.exe is included with SSMS or the SQL Server Command Line Utilities package.
1
Select the large table(s) on the DB Migration tab
In the DB Migration tab, tick each large table in the table list. Multiple tables are processed one at a time.
DB Migration Tab — Table list
coredata.Configuration 2,100,000 rows · 680 MB Large
coredata.ProviderType 890,000 rows · 520 MB Large

Tick the tables too large for direct row-copy. Leave normal tables unchecked.

2
Click BACPAC Seed (Large Tables)
Button is in the toolbar row at the top of the DB Migration tab. It opens the BACPAC configuration dialog.
DB Migration Tab — Toolbar
Run Migration
Resume
Assess
BACPAC Seed (Large Tables) ← click here
3
Fill in the BACPAC Seed dialog
Target fields are pre-filled from the wizard's Target connection tab. Verify the host matches your Azure SQL target server, not the source. Output directory needs free space equal to roughly 1× the table's data size.
BACPAC Seed — Large Table Configuration
BACPAC Seed via SqlPackage
Output directory:
D:\BacpacStaging
Browse…
↑ Local staging folder. Needs ~1× table data size free. Files can be deleted after verification.
RDS host:
sql-target.database.windows.net
Must be the TARGET server — not the source. Pre-filled from the wizard; verify before starting.
RDS port:
1433
RDS database:
cloudbasis_Pubconfig22
↑ Target database name — must already exist on the target server with schema deployed.
RDS username:
sqladmin
RDS password:
••••••••
Run CDC catch-up after import
↑ Recommended ON. Catches any rows written to source during the export/import window.
Start BACPAC Seed
Cancel
4
Monitor progress in the Migration Log
The dialog closes and processing runs in the background. Watch the Migration Log pane.
=== BACPAC Seed: SqlPackage export → Azure SQL import === Tables: coredata.Configuration, coredata.ProviderType Output dir: D:\BacpacStaging [1/2] coredata.Configuration Step 1/3: Exporting via SqlPackage → D:\BacpacStaging\coredata_Configuration.bacpac Successfully exported database and saved it to file '...' Time elapsed 0:00:37.11 Export done: file size 0.01 GB Step 2/3: Importing into Azure SQL target/cloudbasis_Pubconfig22 bcp in → [coredata].[Configuration] (TableData-000-00000.BCP) 2100000 rows copied. Import done. Step 3/3: CDC catch-up for rows written during export/import window CDC catch-up: +12 rows (incremental — lsn_watermark) === BACPAC Seed DONE in 2m 15s ===
When the log shows === BACPAC Seed DONE ===, all selected tables are fully loaded including CDC catch-up rows. Delete the .bacpac staging files after verification.

Path B — Azure SQL Database → AWS RDS for SQL Server (Manual Steps)

The BACPAC Seed button does NOT automate the import step for AWS RDS. bcp.exe bulk-load against RDS is blocked by AWS — RDS does not allow direct inbound bulk connections outside the VPC. You must follow the manual S3-based path below.
Why bcp.exe does not work on AWS RDS

On on-prem SQL Server and Azure SQL Database, bcp.exe connects directly over port 1433 and bulk-loads rows into any table you have write access to.

On AWS RDS for SQL Server, AWS controls the underlying OS. There is no mechanism to push a file directly into the instance — bulk operations must go through Amazon S3 via the managed stored procedures (msdb.dbo.rds_backup_database / rds_restore_database). Attempting bcp against RDS will either time out at the network layer or fail at the bulk-load permission level because ADMINISTER BULK OPERATIONS is not available to RDS users. There is no workaround — AWS deliberately removes this path to maintain managed-instance guarantees.
BACPAC Seed — Azure SQL → AWS RDS (Manual Path)
🗄
Step 1
SqlPackage Export
Azure SQL → .bacpac
(tool button)
Step 2 (manual)
Upload .bacpac
to S3 bucket
in same region as RDS
🔧
Step 3 (manual)
Grant S3 access
to RDS instance
(IAM role / option group)
📥
Step 4 (manual)
SqlPackage /Action:Import
from S3 path
into empty RDS DB

⚠ SqlPackage /Action:Import requires an empty target database. If the RDS database already has schema or data, use native .bak restore via S3 instead (see note below).

1
Export the table to .bacpac using the tool (same as Path A Step 1–3)
Use the BACPAC Seed dialog to run the export only. Set the output directory to a local staging folder with enough free space. The export succeeds normally — only the import step is different for RDS.
2
Upload the .bacpac to an S3 bucket in the same region as your RDS instance
# AWS CLI upload aws s3 cp D:\BacpacStaging\coredata_Configuration.bacpac s3://your-bucket/bacpac/
The S3 bucket must be in the same AWS region as your RDS instance (e.g. us-east-1). Server-side encryption is fine — RDS can read KMS-encrypted buckets if the IAM role has kms:Decrypt.
3
Ensure the RDS instance has S3 access via an IAM role + option group
In the RDS console: Options Groups → SQLSERVER_BACKUP_RESTORE option must be attached with an IAM role that has s3:GetObject and s3:ListBucket on your staging bucket. This is the same setup used for native .bak restores.
-- Verify the option is active: EXEC msdb.dbo.rds_describe_pending_maintenance_actions; -- Confirm S3 integration is attached: SELECT * FROM msdb.dbo.rds_fn_list_options();
4
Run SqlPackage /Action:Import from S3 into an empty RDS database
This step requires the target database to be empty (no tables, no data). If your RDS target already has schema deployed from a previous migration run, use the native backup-restore path instead (see note at the bottom of this section).
# SqlPackage import from S3 URI SqlPackage /Action:Import \ /TargetServerName:your-instance.rds.amazonaws.com \ /TargetDatabaseName:cloudbasis_Pubconfig22 \ /TargetUser:admin \ /TargetPassword:yourpassword \ /SourceFile:s3://your-bucket/bacpac/coredata_Configuration.bacpac \ /TargetEncryptConnection:True \ /TargetTrustServerCertificate:True
Monitor with SELECT * FROM msdb.dbo.rds_task_status — SqlPackage /Action:Import on RDS runs as a managed task, not inline. It may take several minutes to appear in task status.
5
Run CDC catch-up manually (or use the tool's CDC Sync button)
After the import completes, rows written to the source during the export/import window will be missing. Use the tool's Resume or CDC Sync on those tables to catch up the delta.
If the RDS target already has schema/data (not empty): SqlPackage /Action:Import will fail with SQL71659. The correct approach in that case is to export a native .bak backup from on-prem or Azure, upload to S3, and restore with msdb.dbo.rds_restore_database. This replaces the whole database — plan accordingly with a cutover window.

BACPAC Seed is designed for tables that already exist on the target. When you use it against a fresh or partially-migrated target, you will hit a specific cascade of errors that look like failures but are actually sequencing problems. This section gives you the step-by-step sequence to complete a full migration where some tables need BACPAC Seed.

📋
When does this scenario apply?
You have a source database (e.g. cloudbasis_Pubconfig2) with 154 tables. A subset of those tables are very large and must be seeded via BACPAC (e.g. 8 tables). The remaining 146 tables will be copied by the standard migration engine. Run them in this order — do not run BACPAC Seed first.
Correct Order of Operations — Azure → Azure with BACPAC Tables
1️⃣
Main Migration
All 154 tables
Schema + Data
PK-range copy
2️⃣
BACPAC Seed
8 large tables
Import Only mode
(use .bacpac on disk)
3️⃣
Re-apply Schema Objects
Temporal tables
Views / Functions
now succeed
Verify
Row counts
Temporal versioning
Foreign keys

BACPAC Seed step 2 uses the .bacpac files already exported in step 1 — no re-export needed.

Why must the main migration run first?
BACPAC Seed's bcp import step issues bcp schema.table in ... against the target database. If the table doesn't exist yet, bcp returns NativeError 208 — Invalid object name and the import fails. The main migration creates all 154 tables (schema + data) first, so all FK parent tables are in place when BACPAC Seed runs its import. Additionally, the 38 temporal tables and any views/functions that reference BACPAC tables cannot be applied until those tables contain data — run Re-apply Schema Objects last.
1
Run Main Migration — all tables, schema + data
Select all 154 tables in the DB Migration tab. Set sync mode to Full Copy. Tick Migrate Schema and Migrate Data. Click Run Migration.

The BACPAC tables (large ones) will also be copied here via PK-range. That is intentional — this ensures their schema and FK-parent data are on the target. The BACPAC Seed step later will overwrite just the data for the large tables using the fast bcp path.
-- After migration completes, verify tables exist on target: SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA IN ('coredata', 'ruledata', 'salesdata', 'mappingdata', 'rulesdata', 'frqlimitdata', 'diagnosisdata', 'customcpthcpcsdata') ORDER BY TABLE_SCHEMA, TABLE_NAME; -- Expected: all 154 tables returned (TABLE_TYPE = 'BASE TABLE')
PK-range fallback on Azure SQL is expected, not an error. Azure SQL PaaS does not allow BULK INSERT to read from a local file path ("BULK INSERT cannot access a local temp file; use PK-range copy for RDS/Azure SQL targets"). The tool detects this automatically and falls back to PK-range copy — no action needed.
2
Check which .bacpac files are already on disk
If BACPAC Seed was run before the main migration (generating exports before the import could succeed), the .bacpac files are already on disk. Use Import Only mode to skip the 4-hour re-export.
# Check what's in the staging folder (PowerShell) Get-ChildItem "C:\Users\you\Desktop\exeception\*.bacpac" | Select Name, @{N='GB';E={[math]::Round($_.Length/1GB,2)}}
Typical output for 2 already-exported tables:
coredata_Configuration.bacpac 0.01 GB ✓ ready coredata_CustomEditOverrideFilterItemValue.bacpac 1.24 GB ✓ ready # remaining 6 tables need fresh export
3
Open BACPAC Seed — enable Import Only for files already on disk
Click BACPAC Seed (Large Tables). In the dialog:
  • Select all 8 tables
  • Set output dir to the folder containing the .bacpac files
  • Tick "Import only — skip export, use existing .bacpac files"
  • The file status panel shows ✓ for each file found on disk, ✗ for missing files
Files marked ✗ will be freshly exported before import. Files marked ✓ skip the export.
BACPAC Seed Dialog — Import Only Mode
Output directory:
C:\Users\you\Desktop\exeception
Import only — skip export, use existing .bacpac files
coredata_Configuration.bacpac                          ✓ 0.01 GB
coredata_CustomEditOverrideFilterItemValue.bacpac     ✓ 1.24 GB
coredata_PricerParameter.bacpac                         ✗ not found — will export
coredata_ProviderType.bacpac                            ✗ not found — will export
4
Click Start — monitor progress in the Migration Log
The progress bar and status line show which table is active, which step it is on, and how long the run has been going. Tables with existing .bacpac files complete in seconds (import only). Tables needing fresh export show the export duration.
=== BACPAC Seed: Import Only (skipping export) === Tables: coredata.Configuration, dbo.RuleOverrideItemValue, ... Mode: IMPORT ONLY — using existing .bacpac files on disk [1/8] coredata.Configuration Step 1/3: Using existing .bacpac (0.01 GB) — export skipped Step 2/3: Importing... bcp in → [coredata].[Configuration] 2,458,012 rows copied. Import done. [2/8] dbo.RuleOverrideItemValue Step 1/3: Using existing .bacpac (1.24 GB) — export skipped Step 2/3: Importing... bcp in → [coredata].[CustomEditOverrideFilterItemValue] ... === BACPAC Seed DONE in 12m 31s ===
5
Re-apply Schema Objects — temporal tables and functions now succeed
After BACPAC Seed completes, go to the Schema Objects tab and click Re-apply Schema Objects. This retries:
  • Temporal tables: re-enables SYSTEM_VERSIONING = ON for all 38 tables (previously failed because the base tables had no data)
  • Functions / views referencing BACPAC tables (e.g. GetCustomEditIdByConfigurationId — previously failed with NativeError 208 on coredata.Configuration)
Expected outcome: 38 temporal tables versioning re-enabled, 1 function applied, 0 failed.
--- Re-applying schema objects --- Table types: applied 93, 0 failed Schema objects: applied 166, 0 failed --- Temporal tables: re-enabling system-versioning for 38 table(s) --- salesdata.CptMaxUnits: versioning ON ✓ mappingdata.SystemMap: versioning ON ✓ ... (38 total) Temporal tables: 38 re-enabled, 0 failed
6
Final validation — row counts and temporal table state
Run these queries on the target to confirm a clean migration.
-- 1. Row counts for BACPAC tables (compare to source) SELECT 'coredata.Configuration' , COUNT(*) FROM coredata.Configuration UNION ALL SELECT 'dbo.RuleOverrideItemValue', COUNT(*) FROM dbo.RuleOverrideItemValue UNION ALL SELECT 'coredata.ProviderType' , COUNT(*) FROM coredata.ProviderType UNION ALL SELECT 'ruledata.CustomEdit' , COUNT(*) FROM ruledata.CustomEdit; -- 2. Confirm temporal versioning is ON for all 38 tables SELECT OBJECT_SCHEMA_NAME(object_id) + '.' + name AS table_name, temporal_type_desc FROM sys.tables WHERE temporal_type = 2 -- SYSTEM_VERSIONED_TEMPORAL_TABLE ORDER BY table_name; -- All 38 rows should show temporal_type_desc = 'SYSTEM_VERSIONED_TEMPORAL_TABLE' -- 3. Confirm FK parent tables are present (spot check) SELECT COUNT(*) FROM dbo.RuleOverrideItem; SELECT COUNT(*) FROM coredata.Pricer;

Common BACPAC Errors and What They Mean

Error Message Cause Fix
NativeError 208 Invalid object name 'schema.Table' Table does not exist on target — main migration has not run yet Run main migration first (Step 1 above)
Export code 1 SqlPackage export exited with code 1 FK chain includes a temporal table or a table SqlPackage can't include in scope (SQL71564) Check the Migration Log for the exact SQL71xxx error; if the table's data already came from main migration, use Import Only for that table
SQLState 22001 String data right truncation (NativeError 0) bcp native format expects a wider column than what exists on target; column length mismatch between source and target Compare CHARACTER_MAXIMUM_LENGTH for that table in source vs target INFORMATION_SCHEMA.COLUMNS; re-run main migration schema-only for that table
PK-range fallback BULK INSERT cannot access a local temp file; falling back to PK-range copy Azure SQL PaaS does not allow BULK INSERT from local disk — by design No action needed — PK-range copy works correctly; this is informational only
Temporal FAILED ×38 system-versioning FAILED — Invalid object name 'schema.Table' Re-apply ran before data was present; the base temporal tables don't exist or are empty Run Re-apply Schema Objects again after BACPAC Seed and main migration both complete
Schema batch failed FK references invalid table 'dbo.RuleOverrideItem' (1767) BACPAC table has FK to a table outside the 8-table selection scope — parent table not in the batch FK parent tables are created by main migration (all 154 tables); table creates fine once parents exist

BACPAC Seed runs on its own independent background thread — completely separate from the normal migration engine. This means you can run small tables concurrently with BACPAC, but only if they target different tables. The right strategy depends on whether you are going to the same target server or a different one.

Decision: Can I run small tables while BACPAC is running?
Are small tables and BACPAC tables going to the same target server?
YES — same server
Run simultaneously
Use table checkbox split
(see Option 1 below)
NO — different servers
Always parallel
Independent threads,
no coordination needed

BACPAC Seed and Jobs/Run Migration each run on independent daemon threads — they never block each other at the engine level. The only conflict risk is writing to the same table on the same target server simultaneously.

✅ Scenario A — Different target servers (simplest case)

If BACPAC is loading to AWS RDS while Jobs migrates small tables to Azure SQL DR (or on-prem VM), there is zero conflict. Just start both — BACPAC Seed button first, then switch to the Jobs tab and click Run All. Both run fully in parallel.

💾
BACPAC Seed
dbo.AuditLog 680 GB
→ AWS RDS
runs at same time as
🔀
Jobs Tab
all small tables
→ Azure SQL DR
✅ Scenario B — Same target server, different tables (Option 1: recommended)

Split the work by table using the checkbox list on the DB Migration tab:

1
In the table list — check ONLY the large tables
Tick dbo.AuditLog, dbo.ClaimJson etc. Leave small tables unchecked. Click BACPAC Seed — it starts on its own thread.
Table list — select large tables for BACPAC only
dbo.AuditLog 680 GB → BACPAC
dbo.ClaimJson 520 GB → BACPAC
dbo.Customer 1.2 GB → Run Migration
dbo.Product 200 MB → Run Migration
dbo.OrderLine 18 GB → Run Migration
2
Click BACPAC Seed — it starts immediately on its own thread
The BACPAC Seed daemon thread starts exporting dbo.AuditLog.
3
Now uncheck the large tables — check the small tables
Untick AuditLog and ClaimJson. Tick Customer, Product, OrderLine. These are the tables you want the normal row-copy engine to handle.
4
Click Run Migration — small tables copy in parallel with BACPAC
Both run simultaneously. Different tables, same target server — no conflict. The Run tab shows small-table progress while BACPAC logs stream separately. When both finish, all tables are on the target.
What is happening simultaneously
BACPAC thread (background)
Exporting dbo.AuditLog → D:\Staging\dbo_AuditLog.bacpac
… 45% · 4h remaining …
Run Migration thread (normal)
Copying dbo.Customer (2.1M rows) ✓
Copying dbo.Product (480K rows) ✓
Copying dbo.OrderLine … 62%
⏳ Scenario C — Sequential with Resume (safest, zero complexity)

If you want zero risk of any coordination mistake, wait for BACPAC to finish, then click Resume (not Run Migration). Resume automatically detects which tables already have data on the target and skips them — it will only copy the remaining small tables. No need to manually deselect anything.

💾
BACPAC Seed
large tables → done
Resume
skips BACPAC tables
copies remaining only
All tables loaded
no manual deselection
needed
Summary — Which approach for which situation
Situation Approach Parallel? Notes
BACPAC → Server A, small tables → Server B Scenario A ✅ Yes Just start both — independent servers, zero conflict
BACPAC + small tables → same server, different tables Scenario B ✅ Yes Split by table checkbox: large = BACPAC, small = Run Migration
Don't want to manage checkboxes manually Scenario C ⏳ Sequential Wait for BACPAC → click Resume → auto-skips loaded tables
BACPAC + Jobs (both all-table) → same server Avoid ❌ Conflict Jobs copies ALL tables — would overwrite what BACPAC just loaded
The one combination to avoid: running the Jobs tab (which migrates ALL tables) to the same target server at the same time as BACPAC Seed targeting the same server. Jobs would re-create and overwrite the tables BACPAC is actively importing into. Use the table-checkbox split (Scenario B) or wait (Scenario C) instead.
Jobs Tab — Best Practices
  • Always verify the summary text next to the Load button shows the correct host before clicking Run All
  • Use concurrency 1 during your first test run — easier to debug a single log
  • Each job creates the target database automatically if it does not exist
  • The Stop button sets a stop signal — jobs finish the current table before halting
  • Duplicate job warning: if two jobs map to the same source+target+server, the tool asks before proceeding
BACPAC — Watch Out For
  • Disk space: .bacpac is compressed but plan for 50–80% of raw table size on the staging drive
  • Network: import over the internet is slow — run from a VM in the same region as the target
  • SqlPackage times out at 600 seconds by default — for very large tables, run SqlPackage manually with /p:CommandTimeout=0
  • BACPAC imports drop all indexes then rebuild — target DB needs enough tempdb space
  • Not supported for on-prem or RDS source — Azure SQL source only
Override Target — Common Mistakes
  • Forgetting to click Load after selecting a profile — the override is not active until Load is clicked (check for the host summary text)
  • Profile was saved with wrong port — verify at Step 5 → Connection Profiles before running jobs
  • Target DB name field left blank — the job will fail immediately with a "missing database name" warning
  • Firewall not open on target server — test connectivity from Step 5 Test Connection before running jobs
Typical Use Cases
  • DR seeding: migrate same DB to primary RDS + DR RDS in one run
  • Environment promotion: dev → staging → prod simultaneously
  • Multi-region replication: us-east-1 + eu-west-1 in parallel
  • Validation testing: migrate to a test server, validate, then migrate to prod
  • Large table bypass: BACPAC 500 GB table while normal tables copy via row engine
Quick Reference — Jobs Tab Field Summary
Field Where it appears What to enter
Source DB Each job row (top, left of →) Database name on source server (from Step 5 host)
Target DB Each job row (top, right of →) Database name to create/use on the target server
Override target ☑ Each job row (checkbox) Check to redirect this job to a different target server than Step 5
Target profile Override row (appears when checkbox ticked) Select saved connection profile for the target server
Load button Next to Target profile dropdown Must click to activate the override. Server summary appears to the right.
Concurrency Jobs toolbar (top of tab) Max simultaneous jobs. 2–3 recommended for production sources.