Database and SaaS migrations with provable cutovers
Inventory behavior, convert deliberately, move a consistent baseline, capture change, reconcile business invariants, rehearse the switch, and retain a rollback path your operators can execute.
Discover behavior before estimating movement
Storage size and row count influence transfer time. They do not reveal semantic conversion, hidden integrations, unsupported behavior, required outage, or whether the target can run the workload.
Data estate
Schemas, tables, partitions, keys, indexes, views, materialized views, large objects, attachments, history, soft deletes, retention, quality, and growth.
Database behavior
Types, precision, defaults, sequences, constraints, triggers, procedures, packages, jobs, links, extensions, collation, time zones, and transaction assumptions.
Application workload
Queries, plans, concurrency, connection pools, long transactions, batch windows, locks, latency, read/write mix, drivers, retries, and failure handling.
Integration surface
APIs, exports, webhooks, event streams, reports, identity, permissions, service accounts, downstream consumers, and undocumented operational scripts.
Operating objectives
Permitted downtime, recovery point and time, maintenance window, throughput, peak load, rollback window, observability, support ownership, and source retirement.
Data obligations
Personal and regulated data, purposes, legal holds, residency, processors, transfers, encryption, access, deletion, audit trail, and records that must not migrate.
Estimation unit
migration effort = objects requiring disposition + behaviors requiring proof + integrations requiring transition + data volume and change rate + rehearsals + cutover and rollback risk + stabilization and retirement work
Classify every object as compatible, automatically convertible, manually convertible, redesign, archive, or retire. Estimate from sampled conversion and tests in each class—not a universal rate per table.
Choose the simplest transition that meets the outage target
Low downtime adds replication, monitoring, conflict, and failback complexity. If a verified maintenance window is acceptable, an offline move can be safer and cheaper than a long-lived dual system.
| Pattern | Write ownership | Best fit | Main risk |
|---|---|---|---|
| Offline export and import | Source stops accepting writes during final export, validation, and switch | Small or moderate datasets with a usable maintenance window | Outage exceeds the tested window or late validation finds a blocking defect |
| Snapshot plus change capture | Source remains authoritative until lag drains and the cutover establishes the target as writer | Large or busy systems requiring a short write interruption | Missed change types, replication lag, schema drift, or an untested failback boundary |
| Domain-by-domain strangler | Ownership moves for one bounded domain or workflow at a time | Systems that can be decomposed behind stable interfaces | Cross-domain transactions, reporting, and ownership remain coupled |
| Application dual write | Application attempts writes to both targets during transition | Rare cases with explicit idempotency and reconciliation semantics | Partial failure, ordering differences, split brain, and unclear rollback authority |
| Archive and rebuild | New system starts from a deliberately limited operational dataset | Target product differs substantially and old history can remain read-only | Users need history or behavior that was not included in the approved archive plan |
PostgreSQL describes logical replication as an initial snapshot followed by continuing changes. That pattern is useful, but its documented restrictions show why the migration still needs separate schema, sequence, large-object, permission, and switchover work. PostgreSQL architecture · PostgreSQL restrictions.
Oracle to PostgreSQL is a behavior conversion
A heterogeneous migration changes the database contract. Convert schema and executable code, then prove application behavior and data movement separately.
Null and text semantics
Audit application and SQL assumptions around Oracle empty strings, null comparisons, concatenation, default values, uniqueness, and migrated blank data.
Numbers and identifiers
Choose PostgreSQL types from observed range, scale, arithmetic, and index behavior. Test generated identities, sequences, quoted names, case folding, and key allocation.
Date, time, and locale
Make time zone and calendar intent explicit. Test Oracle DATE usage, timestamps, intervals, formatting, collation, sorting, encodings, and daylight-saving transitions.
Stored behavior
Inventory PL/SQL packages, procedures, functions, triggers, jobs, synonyms, links, hints, and exception behavior. Port, move to application code, replace, or retire each item.
Transactions and concurrency
Test isolation assumptions, locks, autonomous work, sequences, retry behavior, long transactions, connection pooling, failover, and duplicate execution.
Plans and operations
Replay representative queries and batches; compare correctness, plans, indexes, latency, throughput, memory, vacuum behavior, backup, restore, monitoring, and privileges.
Conversion tools produce candidates, not proof. AWS's heterogeneous-migration guidance explicitly separates schema and code conversion from data migration. Its product choices are vendor-specific, but the separation is a sound engineering model. AWS guidance.
SaaS migration starts with an object and behavior ledger
Two products rarely expose the same data model or automation semantics. Define the target operating process first, then map every source object, relationship, permission, and workflow to an explicit disposition.
Object mapping
For every object and field record source meaning, target meaning, transform, required state, owner, historical need, validation rule, and loss approval.
Identity and access
Map users, groups, roles, ownership, inactive accounts, external collaborators, service identities, delegated access, and records owned by departed users.
Relationships and history
Preserve stable cross-references, parent-child order, comments, activities, versions, timestamps, attribution, soft deletes, and audit history where the target permits.
Files and rich content
Inventory attachment bytes, names, types, sizes, checksums, links, inline images, generated exports, inaccessible files, and malware or content-policy handling.
Automation and integrations
Recreate triggers, approvals, formulas, workflows, templates, notifications, webhooks, API clients, reporting feeds, and scheduled exports with new identifiers.
API operating limits
Design for pagination, rate limits, retry-after instructions, expiring tokens, resumable checkpoints, idempotency, partial failures, export lag, and schema change.
Extract deterministically
Store API version, tenant, query, filters, cursor, page count, time range, collection timestamps, retry history, raw object identifiers, and rejected responses. A successful HTTP status does not prove a complete export.
Load idempotently
Maintain source-to-target identity mapping, dependency order, transform version, request key, result, rejection reason, retry state, and reconciliation status so a restart cannot silently duplicate data.
Reconcile from structure to business truth
Define the checks, tolerances, exclusion rules, evidence, and approver before the first production copy. Investigate every mismatch; do not normalize unexplained differences into the baseline.
Structure
Expected objects, fields, types, constraints, indexes, views, procedures, permissions, workflows, files, integrations, and explicitly retired items.
Completeness
Eligible records by object and partition, changes after baseline, nulls, distinct keys, rejected items, soft deletes, attachments, users, and relationship counts.
Integrity
Primary and foreign keys, uniqueness, orphan detection, deterministic checksums, file hashes, sequence position, date ranges, identity mapping, and permission equivalence.
Business invariants
Ledger totals, open balances, inventory, subscription state, case status, document counts, lifecycle transitions, regulatory retention, and customer-visible history.
Behavior
Representative reads and writes, queries, reports, automations, approvals, webhooks, batch jobs, integrations, failure recovery, and role-based user journeys.
Operations
Latency, throughput, error rate, replication lag, locks, storage growth, backup and restore, recovery objectives, observability, support runbooks, and on-call response.
A reconciliation result must be reproducible
result = named source snapshot or change position + named target state + versioned query or rule + explicit inclusion and exclusion scope + observed value + tolerance + status + owner + investigation and approval
Cutover is an executable state transition
A runbook assigns authority and evidence for every transition. It states the last safe abort point, the first target write, the rollback consequences after that write, and the person who makes each decision.
Declare readiness
Confirm rehearsed duration, compatible application release, reconciled baseline, healthy change capture, target capacity, backups, credentials, support coverage, communications, and approval.
Establish the boundary
Stop or queue source writes, pause jobs and integrations, record the source change position and time, drain long transactions, and prevent unauthorized writers.
Drain and reconcile
Apply remaining changes, verify zero or accepted lag, set sequences and generated keys, run final structural and business checks, and account for every rejection.
Switch authority
Route target connections, secrets, jobs, integrations, webhooks, and users; confirm the target is the only approved writer and observe real transactions.
Decide or reverse
Compare live health and business invariants to time-bound thresholds. If rollback triggers fire, execute the tested path and reconcile writes made after the boundary.
Stabilize and retire
Monitor intensively, close discrepancies, support users, preserve evidence, revoke migration access, expire temporary infrastructure, archive or delete source data, and test the new recovery path.
Oracle's GoldenGate guidance documents both unidirectional low-downtime migration and reverse replication when failback without losing target-side writes is required. That does not make rollback automatic: topology, supported objects, conflict behavior, capacity, and the application's writer model still need testing. Oracle documentation.
Legacy Python audit: stabilize before changing the floor
A database or SaaS migration often exposes a runtime that cannot be reproduced safely. Establish a testable baseline before upgrading the interpreter, dependencies, framework, driver, and data layer together.
Reproduce
Create a controlled build, dependency lock, test dataset, deployment path, smoke suite, integration harness, and observable baseline for the current application.
Classify
Separate unsupported interpreter, abandoned packages, native extensions, insecure dependencies, framework coupling, data-access behavior, and business logic without tests.
Sequence
Upgrade in bounded increments or isolate with a compatibility layer. Keep database-driver and query changes measurable rather than mixing every modernization at once.
Prove
Run characterization, unit, integration, migration, performance, security, and recovery tests; compare outputs and side effects before moving production traffic.
Python's official lifecycle page is the source of truth for maintained and end-of-life CPython branches. As of this review, Python 3.9 is end-of-life and 3.10 is in security-only status with a scheduled October 2026 end of life; scheduled dates can change. Python version status.
Migration copies are processing, not disposable plumbing
When personal data is involved, document why each staging copy, validation extract, log, rejected-record queue, attachment cache, backup, and support export is necessary; restrict access and location; protect it; and assign deletion or retention behavior.
GDPR principles including purpose limitation, minimisation, accuracy, storage limitation, security, and accountability apply during migration. Controller and processor terms, records of processing, DPIA needs, and international transfers may also require review. This is implementation guidance, not legal advice. GDPR official text.
Delivery gates from assessment to retirement
Each gate reduces a named uncertainty and produces evidence for the next investment decision. Production cutover is not the first time the full path should run.
Assessment
Inventory data, behavior, integrations, workload, obligations, objectives, stakeholders, migration candidates, and incompatibilities; sample the hardest conversions.
Architecture and proof
Choose transition pattern, build the smallest end-to-end slice, test conversion and data movement, define reconciliation, and validate target behavior under load.
Migration factory
Version mappings and transforms, automate resumable extraction and loading, capture change, quarantine rejects, expose progress, and produce reconciliation evidence.
Rehearsal
Run production-scale copies and the complete cutover and rollback runbooks; measure duration, lag, load, manual effort, error recovery, and business validation.
Cutover and stabilization
Execute controlled authority transfer, monitor technical and business signals, reconcile live writes, support users, resolve defects, and close rollback conditions.
Retirement
Confirm retention and legal holds, archive approved history, revoke access and licenses, remove integrations and secrets, dispose of temporary copies, update recovery, and record sign-off.
Database and SaaS migration FAQ
How do you migrate a database with minimal downtime?
Load a consistent baseline into the target, capture and apply source changes, validate schema and data continuously, rehearse the cutover, then use a short controlled write boundary to drain lag and establish one authoritative writer. Minimal downtime depends on source capabilities, change rate, transformation complexity, application compatibility, and rollback design. It should be a measured target, not a blanket promise.
What makes an Oracle-to-PostgreSQL migration difficult?
The difficult part is usually behavior rather than row copying. Teams must translate data types, empty-string and null assumptions, date and time semantics, sequences, identifiers, packages, stored procedures, triggers, jobs, links, optimizer assumptions, and application SQL. Every converted object needs a disposition and behavioral test; automatic conversion output is a starting point, not acceptance evidence.
How do you prove that migrated data is complete?
Reconcile at several levels: source and target object inventory, eligible row counts, null and distinct distributions, financial or domain totals, key ranges, referential integrity, deterministic hashes where representations match, attachment manifests, permission assignments, rejected records, and changes captured during validation. Define tolerances and owners before the migration begins.
Can a SaaS-to-SaaS migration preserve everything?
Often not. Target APIs may not expose equivalent objects, historical audit entries, original timestamps, identities, permissions, automations, comments, soft-deleted records, or attachment metadata. The project should classify each source field and behavior as migrate, transform, archive, recreate, or intentionally retire, then obtain owner approval for every loss or semantic change.
When is dual writing safe during a migration?
Only when ownership, ordering, idempotency, conflict handling, and reconciliation are explicit. Application-level dual writes can create split-brain states when one write succeeds and the other fails. A single authoritative writer plus change-data capture is usually easier to reason about. If bidirectional writes are unavoidable, test conflict resolution and failback under real failure modes.
What should a legacy Python audit include before migration?
Inventory the interpreter and operating system, deployed entry points, dependencies and native extensions, database drivers, framework versions, build and release process, scheduled jobs, external integrations, secrets, observability, test coverage, data access, and runtime behavior. Reproduce the current application first; then choose upgrade, containment, partial replacement, or retirement per component.
Primary sources and status
Reviewed 2 September 2026. PostgreSQL and Python links are official project documentation. AWS and Oracle links are vendor guidance for their products and should not be treated as neutral tool selection. GDPR is binding EU law. Yarify's migration method and checklists are engineering recommendations.
- PostgreSQL documentation — Logical replicationOfficial publish-and-subscribe architecture for initial table synchronization and continuing row-level changes
- PostgreSQL documentation — Logical replication restrictionsOfficial limitations covering schema and DDL, sequences, large objects, relation types, replica identity, and switchover preparation
- AWS Prescriptive Guidance — Heterogeneous Oracle migrationsVendor guidance distinguishing schema and code conversion from data movement when source and target database engines differ
- Oracle GoldenGate documentation — Online migration and fallbackVendor documentation for initial load, continuing replication, switchover, and reverse replication where failback is required
- Python Developer’s Guide — Status of Python versionsOfficial lifecycle table for maintained, security-only, prerelease, and end-of-life CPython branches
- Regulation (EU) 2016/679 — General Data Protection RegulationBinding EU law relevant to purpose limitation, minimisation, accuracy, security, processors, records, DPIAs, retention, and transfers
