oracle to aurora postgresql · 2026 migration guide

Oracle to Aurora PostgreSQL — the heterogeneous migration, done properly.

This is the deep version: you have decided to leave Oracle and land on Amazon Aurora PostgreSQL, and now you need to actually convert it. We walk the whole heterogeneous path — what AWS SCT auto-converts and which PL/SQL fights back (packages, sequences, autonomous transactions, CONNECT BY), how DMS full-load plus change-data-capture keeps Aurora live until cutover, the application data-access-layer changes nobody scopes upfront, how you validate that the data and behavior actually match, and a cutover with a real rollback. AWS MAP and database-migration funding can cover most or all of it, partner-led.

database TCO cut
60–90%
auto-convertible schema
70–95%
cutover downtime
minutes
cost to you (MAP)
low / $0
TL;DR
  • Oracle to Aurora PostgreSQL is a heterogeneous migration — you change the database engine, so unlike an Oracle-to-RDS lift-and-shift, the schema and procedural code must be converted, not copied. The reward is permanent: the Oracle license, the ~22% annual support renewal, and the per-option fees disappear, typically cutting database TCO 60–90%. The cost is one-time conversion engineering, and its size is set almost entirely by how much PL/SQL you have and how Oracle-specific it is.
  • The toolchain is AWS Schema Conversion Tool (SCT) for schema + code and AWS Database Migration Service (DMS) for data. SCT converts tables, indexes, views, sequences, and PL/SQL into PostgreSQL, and — more usefully — produces an Assessment Report that names every object it cannot auto-convert and rates it simple/medium/complex. DMS then does a full load followed by change-data-capture (CDC) that reads Oracle’s redo logs and keeps Aurora in sync with live production until you cut over, so user-visible downtime is minutes, not a weekend.
  • The work people under-scope is not the data move — DMS handles that — it is the PL/SQL rewrites (packages, autonomous transactions, hierarchical queries, BULK COLLECT), the application data-access layer (SQL dialect, sequence/identity handling, empty-string-is-NULL, driver swap), and validation/performance tuning on a planner that behaves differently from Oracle’s. CloudRoute routes you to a vetted AWS partner who has done this before and runs it end to end, with the AWS Migration Acceleration Program (MAP) funding qualifying migrations — so the project that pays for itself is also largely AWS-funded.
framing

IWhat actually changes when you go heterogeneous

A homogeneous Oracle→Oracle move (to Amazon RDS for Oracle) copies bytes — same engine, same SQL, same PL/SQL, no rewrite. Oracle→Aurora PostgreSQL is the other kind of migration: the engine changes, so the schema, the procedural code, and the application’s assumptions about the database all have to be translated. That distinction governs everything below.

If you are still weighing lift-and-shift to RDS for Oracle against this re-platform, start with the broader decision page — Oracle to AWS lays out both paths and when each wins. This page assumes the decision is made: the database carries real Oracle licensing cost, it is tractable enough to convert, and your team will own PostgreSQL going forward. From here, the goal is to do the conversion well.

The target is Amazon Aurora PostgreSQL — a PostgreSQL-compatible engine with cloud-native storage that auto-scales to 128 TiB, replicates six ways across three Availability Zones, supports up to fifteen low-latency read replicas, and (the entire point) carries no database license. You pay for compute, storage, and I/O. Aurora is wire-compatible with community PostgreSQL, so the conversion target is "idiomatic PostgreSQL," and everything PostgreSQL-native — drivers, extensions, the planner — applies.

The honest mental model: roughly 80% of the calendar on a serious Oracle→Aurora project is not moving data. It is converting and rewriting the procedural code, changing the parts of the application that spoke Oracle, validating that behavior matches, and tuning a different query planner. DMS makes the data movement almost boring. The engineering lives in the schema and the application. The next sections follow that reality in order.

step 1 — convert the schema

IIAWS SCT: what auto-converts, and the assessment that becomes your plan

The Schema Conversion Tool does two jobs. It converts the schema and code it can, and — far more valuable on day one — it produces an Assessment Report that tells you object-by-object what it cannot, rated by difficulty. That report is the only honest way to size the project before you commit budget.

You point SCT at the source Oracle database and the target Aurora PostgreSQL endpoint and let it analyze the whole schema: tables, indexes, constraints, views, sequences, and the procedural code (packages, procedures, functions, triggers). It converts what it can and flags the rest, classifying each remaining action item as simple, medium, or complex. The headline number — percent of objects auto-converted — typically lands between 70% and 95%, and where you fall in that band is almost entirely a function of how much PL/SQL you carry and how Oracle-specific it is.

The structural layer converts cleanly almost every time. Datatype mapping is mostly mechanical: Oracle NUMBER lands on PostgreSQL numeric / bigint / integer depending on precision and scale, VARCHAR2 becomes varchar, DATE becomes timestamp (Oracle DATE carries a time component — a classic silent trap if you assume it is date-only), CLOB becomes text, BLOB becomes bytea, and RAW/ROWID need explicit decisions. SCT does the mapping and flags the NUMBER columns whose precision a human should confirm. Tables, indexes, views, and check constraints come across with little drama. The hours go somewhere specific and predictable, and naming them up front is what keeps a project from stalling mid-stream.

  • Packages — the biggest structural gap. PostgreSQL has no native package. SCT maps each Oracle package to a PostgreSQL schema holding the individual functions and procedures, but package-level shared state (package variables that persist for a session), initialization blocks, and overloaded signatures need manual redesign — often into per-session GUC settings, a temp table, or explicit parameters.
  • Autonomous transactions. Oracle’s PRAGMA AUTONOMOUS_TRANSACTION (commit inside a nested transaction independent of the caller — the classic audit/logging pattern) has no direct PostgreSQL equivalent. It is redesigned, commonly via the dblink extension making a loopback connection, or by refactoring the pattern away (e.g., queue the log row and write it outside the transaction).
  • Hierarchical queries. Oracle CONNECT BY / START WITH / PRIOR rewrites to PostgreSQL WITH RECURSIVE common table expressions. SCT converts many cases automatically; deep or cyclic hierarchies, plus LEVEL / SYS_CONNECT_BY_PATH / CONNECT_BY_ROOT, often need a hand-written recursive CTE.
  • Sequences and identity. seq.NEXTVAL / seq.CURRVAL map to nextval('seq') / currval('seq'), but the idioms differ: PostgreSQL favors GENERATED ... AS IDENTITY or serial-backed defaults, and any trigger that populated a key from a sequence on insert is usually replaced by a column default. Caching, increment, and CURRVAL-without-a-prior-NEXTVAL semantics all need checking.
  • Bulk operations and collections. BULK COLLECT, FORALL, and PL/SQL associative arrays / nested tables have no one-to-one mapping. In heavy ETL packages these are common rewrites — often re-expressed as set-based SQL (which PostgreSQL prefers anyway) or array operations.
  • Built-in and semantic differences. DECODE → CASE, NVL → COALESCE, NVL2, ROWNUM → LIMIT / row_number(), SYSDATE/SYSTIMESTAMP semantics, the (+) outer-join operator, MERGE quirks, and Oracle treating an empty string as NULL while PostgreSQL does not — each is small, but collectively they are the long tail of medium action items.
  • Triggers, materialized views, and partitioning. Trigger syntax and firing semantics differ; Oracle materialized-view fast-refresh has no exact analog (PostgreSQL refreshes are full or concurrent); and Oracle partitioning strategies map to PostgreSQL declarative partitioning but not always one-for-one.

For the genuinely hard objects, SCT can deploy an extension pack and, for some constructs, emulate Oracle behavior on the PostgreSQL side rather than rewriting it by hand. Treat that as a pragmatic accelerator and as technical debt — useful for the long tail, not a license to skip idiomatic rewrites of code that runs hot. The disciplined sequence is: take the auto-converted objects, manually rewrite the medium/complex action items into clean PL/pgSQL, and reserve emulation for the cases a proper rewrite cannot yet justify.

The most valuable artifact of this phase is not the converted schema — it is the number plus the action-item list. "This database is 88% auto-convertible with 240 complex items, concentrated in three ETL packages and the audit framework" is a project you can staff and schedule. A 95%-convertible reporting mart is a quick win; a 72%-convertible core-transaction schema with six-figure PL/SQL line counts is a real engineering program. SCT lets you make that call with evidence instead of optimism.

The PL/SQL that fights back

Oracle’s PL/SQL is a richer procedural language than PostgreSQL’s PL/pgSQL, so the gaps are concrete. These are the objects that consume the manual conversion budget on essentially every Oracle→Aurora migration:

a note on Babelfish (and why it is not your shortcut)

Teams researching Oracle migration often hit Babelfish for Aurora PostgreSQL and hope it is a fast lane. It is not — for Oracle. Babelfish is a translation layer that lets Aurora PostgreSQL understand Microsoft SQL Server’s T-SQL and TDS wire protocol, so applications keep their SQL Server queries. There is no equivalent that makes Aurora speak Oracle’s PL/SQL or SQL*Net. For Oracle→Aurora the path is genuine conversion via SCT + DMS. (If part of your estate is SQL Server, Babelfish is very relevant there — see SQL Server to AWS.)

step 2 — move the data

IIIAWS DMS: full load, then CDC to a near-zero-downtime cutover

With the schema built on Aurora, the Database Migration Service moves the data and — the part that matters — keeps it moving. DMS change-data-capture is what turns a dreaded weekend cutover into a controlled switch measured in minutes.

A DMS task runs in up to three modes. Full load bulk-copies existing rows from Oracle into Aurora. CDC then reads Oracle’s redo logs and continuously applies every subsequent insert, update, and delete to Aurora. Run "full load plus CDC" and DMS first copies the data, then settles into a steady state where Aurora trails live Oracle by seconds. The source stays fully online throughout — users never know a migration is underway. You can let that replication run for days or weeks while you validate, test the application against Aurora in staging, and tune performance.

Operationally there are real knobs, and a seasoned migration team turns them deliberately. The replication instance is sized to the change rate; high-volume systems are parallelized across multiple tasks split by table or schema. Large-object (LOB) columns need explicit handling — full LOB mode is complete but slow, limited LOB mode is fast but truncates beyond a set size — so you choose per workload. For best throughput on the initial load you typically create secondary indexes, foreign keys, and triggers after the full load rather than before, then enable them for the CDC phase. And CDC requires Oracle supplemental logging enabled on the source so the redo stream carries enough column data to replay changes.

Be clear about DMS’s boundary: it replicates row changes, not logic. It does not migrate procedural code (that is SCT’s job and your rewrites), it does not convert schema, and it will not invent referential integrity you did not define. DMS moves and syncs the data; SCT and your engineers move the behavior. Keeping that line crisp is what prevents the "we thought DMS handled the triggers" surprise late in a project.

Proving the data actually matches

DMS includes built-in data validation that compares source and target row-by-row after the full load and during CDC, reporting mismatches rather than asking you to trust the pipe. For anything mission-critical this is non-negotiable: you validate row counts, run checksums on the critical tables, and add application-level reconciliation queries that re-compute key business aggregates on both sides. The pairing — DMS validation for fidelity plus your own business reconciliation for meaning — is what lets a CFO, an auditor, or a regulator accept that the Aurora copy is now the system of record.

step 3 — the part teams forget

IVThe application data-access layer: where the hidden work hides

SCT converts the database and DMS moves the data, but neither touches your application. A surprising amount of Oracle-specific behavior lives in the app tier — the SQL your code emits, the driver it loads, and the assumptions it makes — and scoping this honestly is the difference between a 4-month project and a 9-month one.

Start with the connectivity layer. Oracle clients use the oracle JDBC driver / OCI / SQL*Net and an Oracle connection string and SID/service name; Aurora PostgreSQL uses the PostgreSQL JDBC (or libpq, psycopg, node-postgres, etc.) driver and a standard PostgreSQL DSN. ORMs and query builders need their dialect switched (Hibernate dialect, Django/Rails/Sequelize adapter, SQLAlchemy URL). This is mechanical but touches configuration, secrets, and every service that holds a connection — and connection-pool behavior differs enough that you tune pool sizes for PostgreSQL rather than assume the Oracle settings carry over.

Then the SQL the application emits directly — the inline queries, the report builders, the stored-SQL fragments that never went through SCT because they live in application code, not the database. These carry the same dialect gaps SCT flagged in the schema: ROWNUM and Oracle pagination become LIMIT/OFFSET or keyset pagination; (+) outer joins become ANSI joins; NVL/DECODE/SYSDATE need translating; sequence access changes; and — the subtle one that bites in production — Oracle treats '' (empty string) as NULL while PostgreSQL treats it as a zero-length string, so WHERE col = '' and IS NULL checks behave differently. Case-sensitivity of unquoted identifiers and date/number formatting via NLS settings differ too.

Finally, behaviors your code may quietly depend on: default transaction isolation and locking semantics differ between Oracle and PostgreSQL; sequence-generated IDs may not be perfectly gap-free; and anything that read CURRVAL, used Oracle hints, or relied on implicit type coercion needs review. None of this is exotic, but it is invisible until you go looking, which is exactly why a partner who has migrated applications off Oracle inventories the data-access layer during assessment rather than discovering it during cutover.

step 4 — validate behavior

VTesting, validation, and performance on a different planner

Correct data is necessary but not sufficient. The application has to behave identically and perform acceptably on an engine whose optimizer makes different choices than Oracle’s. This phase is where re-platforms are actually de-risked.

Run validation on three levels. Data fidelity comes from DMS validation plus your reconciliation queries (covered above). Functional correctness comes from your application regression suite executed against Aurora — ideally the full suite, with particular attention to the converted PL/pgSQL objects and any code path that touched the rewritten SQL. Behavioral equivalence comes from comparison testing: run representative read and write workloads against both Oracle and Aurora and diff the results, which surfaces the empty-string-is-NULL and date-truncation class of bugs that pass unit tests but change query results.

Performance is its own workstream because PostgreSQL’s planner is not Oracle’s. Queries that were fast on Oracle can choose a different plan on Aurora; you tune by running production-representative load against Aurora before cutover, reading EXPLAIN ANALYZE, adding or reshaping indexes (PostgreSQL partial and expression indexes are powerful here), and making sure autovacuum and statistics (ANALYZE) are configured so the planner has good estimates. Connection pooling — PgBouncer or RDS Proxy — usually matters more on PostgreSQL than teams expect for high-concurrency apps. Budget an explicit tuning phase; "it was instant on Oracle" is not a guarantee on day one, and discovering that in production is the avoidable failure mode.

The discipline that makes all of this tractable is sequencing: migrate a non-critical database first to prove the toolchain and the team’s PostgreSQL muscle, then graduate to the systems the business runs on. The first migration teaches you your own application’s Oracle-isms cheaply; the critical one then benefits from a rehearsed process rather than a first attempt.

step 5 — cut over safely

VICutover and rollback for a database the business runs on

The conversion and the data move are engineering. The cutover is risk management. For a system the business depends on, the entire migration is judged on one question: what happens if something is wrong at the moment of switch?

The answer is a rehearsed runbook with a rollback you do not have to invent under pressure. The single most important design choice is to keep the source Oracle database authoritative until the cutover is proven. Because DMS CDC syncs Aurora from Oracle (not the reverse), rollback during the window is trivial: if validation fails after you switch, you repoint the application back to Oracle, which never stopped being correct. You only burn that bridge once you are certain. A typical mission-critical cutover runs like this:

  • Pre-cutover (days before) — Aurora live under CDC, trailing Oracle by seconds. Full regression suite green against Aurora. DMS validation clean and reconciliation queries matching. Performance tested at production load with plans tuned. Rollback runbook written and rehearsed in staging.
  • Cutover window (the minutes that matter) — Announce a short maintenance window. Stop application writes to Oracle. Let DMS apply the final change backlog until Aurora is fully caught up. Run final row-count and checksum reconciliation. Repoint connection strings / endpoints to Aurora.
  • Smoke test on Aurora — Execute the critical-path transactions — login, the core write paths, a representative report — against Aurora before reopening to users. A scripted smoke test takes minutes and catches the connection-string-typo and missing-grant class of failure immediately.
  • Go / no-go decision — If smoke tests pass, reopen traffic on Aurora and watch error rates and latency closely. If anything is wrong, execute rollback: repoint to Oracle, reopen, debug Aurora offline. Because Oracle was never demoted, rollback costs minutes, not data.
  • Post-cutover stabilization — Keep Oracle running read-only as a safety net for a defined window — commonly one to four weeks — while Aurora proves itself in production, then decommission Oracle and stop the support renewal. That decommission date is the day the savings actually start.

None of this removes risk entirely — a heterogeneous migration of a core system is genuinely hard — but migrating non-critical databases first, rehearsing the cutover, and keeping the rollback explicit converts an unbounded risk into a bounded, reversible event. That discipline is precisely what you are paying a vetted migration partner for, and precisely what AWS MAP funds them to execute well.

the business case

VIIThe license-savings model that justifies the conversion

The conversion costs real engineering, so the model has to clear it. For Oracle→Aurora it almost always does, because the recurring Oracle bill it deletes is large and perpetual while the conversion is one-time.

Build it on three lines. First, the Oracle cost you delete: licenses (per processor, after the core-factor multiplier), the ~22% annual support renewal, the options the schema depends on (Partitioning, Advanced Compression, Diagnostics and Tuning Packs, Active Data Guard, RAC) — each licensed separately and per-core — plus the hardware refresh and DR standby if you run it yourself. A single Oracle Enterprise Edition processor license lists around $47,500, and one physical core often counts as more than one "processor" once the core-factor table is applied, so a mid-sized estate carries a seven-figure annual Oracle bill before anything new ships. Second, the Aurora cost you take on: compute (instance hours or Aurora Serverless v2 capacity), storage, I/O, and backups — with no license layer at all. Third, the one-time conversion: SCT/DMS work, PL/SQL and application rewrites, testing, and cutover — the line MAP and database-migration funding are designed to offset.

In practice, moving a workload off Oracle Enterprise Edition with options to Aurora PostgreSQL cuts database TCO by roughly 60–90%. It skews higher when you were paying for expensive options and a DR standby — Aurora provides Multi-AZ HA, automated backups, and read replicas natively, with no per-feature licensing — and lower when you were already on Standard Edition. Payback on the conversion is commonly under a year on the support renewal alone, which is why these projects survive CFO scrutiny that kills most "modernization" initiatives. The one caveat that keeps the model honest: the savings are real only after decommission. While Oracle runs in parallel as a safety net you are paying for both, so the decommission date is a line item, not an afterthought.

how CloudRoute fits

VIIIMAP + database-migration funding: a partner runs it, AWS funds most of it

A funded, done-for-you Oracle→Aurora migration is the CloudRoute mechanism. You do not assemble an internal SCT/DMS team from scratch and learn PostgreSQL’s edge cases live on a production database — you get matched to a vetted AWS partner who has done heterogeneous Oracle migrations before, and AWS funding covers most or all of the engagement.

The vehicle is the AWS Migration Acceleration Program (MAP), run through the AWS Partner Network in three phases. Assess is a TCO and readiness analysis — the partner runs SCT across your Oracle databases to produce the auto-convertibility numbers, the action-item inventory, and a real savings model; this phase is frequently AWS-funded and gives you go/no-go data before you commit a dollar. Mobilize builds the AWS landing zone and pilots the conversion of a representative database. Migrate & Modernize is the production conversion, the CDC cutover, and stabilization. AWS provides credits and funding scaled to the migration’s size across these phases, and there are AWS programs aimed specifically at database migrations off commercial engines like Oracle.

The honest framing matters: MAP funding applies to qualifying migrations — typically those with a meaningful committed AWS spend after migration — and the exact amount is scoped during Assess. For a substantial Oracle estate that clears the bar, the conversion can be largely or entirely AWS-funded. For smaller workloads that do not qualify for full funding, the value is still real: a partner who has converted Oracle PL/SQL and run DMS CDC cutovers de-risks the hardest parts, rather than your team meeting SCT’s extension pack and PostgreSQL’s planner for the first time on a system the business runs on.

CloudRoute’s role is the routing. You tell us the shape of the estate — how much Oracle, which editions and options, how much PL/SQL, what the databases do, your timeline — and we match you to a partner with a genuine Oracle→Aurora track record and the AWS tier to file MAP. The partner runs the assessment, scopes the funding, and executes. AWS funds the engagement; the partner is paid through MAP; CloudRoute is paid a commission by the partner. You see no invoice from us.

where this connects

For the data-movement engine in depth, see AWS Database Migration Service. The funding mechanics tie into the AWS credits cluster — $100K AWS credits and how AWS POC funding works. The platform you land on should be a secure, multi-account AWS landing zone. And the migration offer page lays out exactly what a CloudRoute-routed, MAP-funded migration includes.

feature-by-feature

Oracle features → Aurora PostgreSQL equivalents + conversion difficulty

This is the table the conversion turns on: for each Oracle construct, what it becomes on Aurora PostgreSQL and how hard SCT plus your engineers have to work to get it there. "Easy" is largely automatic; "hard" is where the manual PL/SQL budget goes.

Oracle featureAurora PostgreSQL equivalentConversion difficulty
Tables, indexes, views, check constraintsDirect equivalentsEasy — SCT auto-converts
Datatypes (NUMBER, VARCHAR2, DATE, CLOB, BLOB)numeric/int, varchar, timestamp, text, byteaEasy–Medium — DATE carries time; NUMBER precision needs review
Sequences (NEXTVAL / CURRVAL)Sequences + GENERATED AS IDENTITY / serial defaultsMedium — idiom + insert-trigger pattern changes
Hierarchical queries (CONNECT BY / START WITH)WITH RECURSIVE common table expressionsMedium — deep/cyclic cases hand-written
Built-ins (DECODE, NVL, ROWNUM, SYSDATE)CASE, COALESCE, LIMIT/row_number(), now()/clock_timestamp()Medium — many auto, semantics differ subtly
Triggers & materialized viewsPostgreSQL triggers; full/concurrent matview refreshMedium — firing semantics + no fast-refresh analog
PartitioningDeclarative partitioningMedium — strategy maps, not always 1:1
PackagesSchema of functions/proceduresHard — no native package; state & overloading manual
Autonomous transactions (PRAGMA)dblink loopback or pattern redesignHard — no direct equivalent
BULK COLLECT / FORALL / collectionsSet-based SQL or array operationsHard — common rewrite in heavy ETL
Empty-string = NULL semanticsEmpty string ≠ NULL (must reconcile in app + SQL)Hard to find — silent behavioral bug if missed
RAC / Active Data Guard / Partitioning optionsNative Aurora HA, replicas, backups (no license)N/A — replaced, not converted (this is the savings)
SCT’s Assessment Report rates every object on this spectrum for YOUR schema and gives a single auto-convertibility percentage (typically 70–95%). The volume of "hard" items — packages, autonomous transactions, bulk collections, and application-side empty-string assumptions — is what sets the timeline. Run the assessment before committing a date.
ready to size the conversion?
Start with a MAP Assess: real SCT auto-convertibility numbers before you commit a date
Start in 3 minutes →
a recent match

A core order database, converted off Oracle to Aurora — anonymized

inquiry · subscription-commerce platform, core Oracle OLTP, US + EU
Series-B subscription-commerce platform, Oracle Enterprise Edition (Partitioning + Diagnostics Pack) on a 2-node RAC cluster, ~$620K/year all-in Oracle cost, one core order/billing database (~3.1 TB) plus two reporting databases

Situation: Oracle support renewal nine months out and a board mandate to cut infrastructure cost. The core order/billing database held ~95K lines of PL/SQL — including an audit framework built on autonomous transactions, three heavy nightly ETL packages using BULK COLLECT, and a category tree driven by CONNECT BY. The application was a Java/Hibernate monolith plus two Node services, all on the Oracle JDBC driver, with a few hundred inline queries using ROWNUM pagination and (+) joins. No one on staff had run a heterogeneous Oracle→PostgreSQL migration.

What CloudRoute did: Routed within 24 hours to an AWS Premier partner with a database-modernization specialization and a documented Oracle→Aurora track record. MAP Assess (AWS-funded) ran SCT: the two reporting databases came back 94–96% auto-convertible; the core OLTP database 81%, with the heavy items concentrated exactly where expected — the autonomous-transaction audit framework, the three ETL packages, and the CONNECT BY hierarchy. The partner converted the reporting databases first as the toolchain pilot, then rewrote the core PL/SQL into idiomatic PL/pgSQL (audit moved to a queue-and-write-outside-txn pattern; ETL re-expressed as set-based SQL; hierarchy as WITH RECURSIVE), swapped the application to the PostgreSQL JDBC driver and pg adapters, and remediated the inline SQL. DMS full-load + CDC ran 6 weeks in sync under full regression and production-load testing; the core database cut over in a 26-minute window with a rehearsed rollback to Oracle that was never needed.

Outcome: All three databases live on Aurora PostgreSQL over ~6.5 months. Oracle decommissioned on schedule — annual database TCO down ~78% (from ~$620K to ~$135K on Aurora, including Serverless v2 for the reporting workloads). A two-week post-cutover performance-tuning pass (new indexes, PgBouncer pooling, autovacuum tuning) closed the gap on three slow report queries. The engagement was MAP-funded against the post-migration AWS commitment; CloudRoute’s commission was paid by the partner. The customer paid $0 for the migration itself.

core DB: 3.1 TB / ~95K LOC PL/SQL · timeline: ~6.5 months · database TCO cut: ~78% · cutover downtime: 26 min · migration cost to customer: $0 (MAP-funded)

faq

Common questions

What is the difference between Oracle to Aurora and an Oracle-to-RDS lift-and-shift?
Oracle to Amazon RDS for Oracle is homogeneous — the same Oracle engine, now managed by AWS. You copy the data (Data Pump or DMS), the SQL and PL/SQL are unchanged, there is no application rewrite, and you are live in weeks — but you keep the Oracle license bill. Oracle to Aurora PostgreSQL is heterogeneous — the engine changes, so the schema and procedural code are converted with AWS SCT, the data moves via DMS, and the application’s Oracle-specific SQL and driver change. It takes longer (typically 4–9 months for a substantial database) but deletes Oracle licensing entirely, cutting database TCO 60–90%. If you have not made that decision yet, the broader Oracle-to-AWS page compares both paths and when each wins.
How much of an Oracle schema converts to Aurora PostgreSQL automatically?
AWS SCT typically auto-converts 70–95% of objects, and it tells you the exact percentage for your schema in its Assessment Report. The structural layer — tables, indexes, views, check constraints — converts cleanly almost every time, and datatype mapping is mostly mechanical. The percentage drops with the volume and Oracle-specificity of your PL/SQL: packages, autonomous transactions, BULK COLLECT/FORALL, and complex CONNECT BY hierarchies are the constructs that need manual rewriting. The Assessment Report classifies every non-auto-converted object as simple, medium, or complex, which is what lets you size the project honestly before committing a date.
Which Oracle PL/SQL features are hardest to convert, and what do they become?
The predictable hard spots: packages (PostgreSQL has no native package — SCT maps them to a schema of functions, but package-level state and overloading are manual); autonomous transactions (PRAGMA AUTONOMOUS_TRANSACTION has no equivalent — redesigned via dblink loopback or by refactoring the logging/audit pattern); hierarchical queries (CONNECT BY / START WITH become WITH RECURSIVE CTEs); and bulk operations (BULK COLLECT, FORALL, associative arrays become set-based SQL or array operations). On top of those is the long tail of built-in and semantic differences — DECODE→CASE, NVL→COALESCE, ROWNUM→LIMIT/row_number(), SYSDATE semantics, and Oracle treating an empty string as NULL while PostgreSQL does not. SCT auto-converts many and can emulate some via an extension pack; the medium/complex items get hand-rewritten into idiomatic PL/pgSQL.
Does DMS migrate my stored procedures and triggers too?
No. AWS DMS moves data, not logic. It performs the full load of existing rows and then replicates live inserts/updates/deletes via change-data-capture, keeping Aurora in sync with Oracle until cutover. It does not convert schema or procedural code — that is AWS SCT’s job plus your manual PL/SQL rewrites. The clean division of labor: SCT converts the schema, packages, procedures, functions, and triggers (flagging what needs manual work); your engineers rewrite the flagged items into PL/pgSQL; DMS moves and continuously syncs the data. Expecting DMS to carry the triggers or packages is the most common scoping mistake on these projects.
Can Babelfish help me migrate Oracle to Aurora PostgreSQL?
No — Babelfish is for SQL Server, not Oracle. Babelfish for Aurora PostgreSQL is a compatibility layer that lets Aurora understand Microsoft SQL Server’s T-SQL dialect and TDS wire protocol, so SQL Server applications can connect with minimal changes. There is no equivalent layer that makes Aurora speak Oracle’s PL/SQL or SQL*Net. For Oracle, the path is genuine heterogeneous conversion with AWS SCT (schema + code) and AWS DMS (data + CDC). If part of your estate is SQL Server, Babelfish is highly relevant there — but it does nothing for Oracle migrations.
What application changes does an Oracle-to-Aurora migration require?
More than teams expect, because SCT only touches the database. You swap the Oracle JDBC/OCI driver and SQL*Net connection string for the PostgreSQL driver and DSN, and switch your ORM dialect (Hibernate, Django, Rails, SQLAlchemy, Sequelize). You remediate the SQL your application emits directly — ROWNUM pagination becomes LIMIT/OFFSET, (+) outer joins become ANSI joins, NVL/DECODE/SYSDATE are translated, and sequence access changes. The subtle one to hunt down: Oracle treats an empty string as NULL while PostgreSQL does not, so equality and IS NULL checks can behave differently. Connection pooling (PgBouncer or RDS Proxy) and transaction-isolation assumptions also need review. A partner inventories this data-access layer during assessment rather than discovering it at cutover.
How much downtime does the cutover to Aurora require, and how do you roll back?
Minutes, done right. Because DMS change-data-capture keeps Aurora continuously in sync with live Oracle, the cutover is just: stop writes to Oracle, let DMS apply the final seconds of changes, run reconciliation, smoke-test critical paths on Aurora, and repoint the application. Rollback is built into the design: since CDC syncs Aurora from Oracle (not the reverse), Oracle stays authoritative and correct throughout the window, so if validation fails you simply repoint the application back to Oracle — minutes, no data loss. The weeks of conversion, validation, and performance tuning all happen invisibly while production keeps running on Oracle. Oracle is kept read-only as a safety net for one to four weeks before being decommissioned.
How much does Oracle to Aurora save, and can AWS fund the migration?
Moving a workload off Oracle Enterprise Edition with options to Aurora PostgreSQL typically cuts database TCO 60–90% — you delete the per-processor license, the ~22% annual support renewal, and the separately-licensed options (Partitioning, Diagnostics, RAC, Active Data Guard), and Aurora provides Multi-AZ HA, backups, and read replicas natively with no per-feature licensing. Payback on the one-time conversion is commonly under a year on the support renewal alone; the savings are real only after you decommission Oracle. On funding: the AWS Migration Acceleration Program (MAP) funds partner-led migrations in three phases — Assess (often AWS-funded, and where the timeline is sized from real SCT numbers), Mobilize (landing zone + pilot), and Migrate & Modernize — scaled to migration size, with programs aimed specifically at database migrations off Oracle. Funding applies to qualifying migrations (meaningful committed AWS spend post-migration); for a substantial estate the work can be largely or entirely AWS-funded. CloudRoute routes you to a vetted partner with the track record and AWS tier to file MAP; the partner is paid through MAP and pays CloudRoute a commission — you see no invoice from us.

Get a funded, done-for-you Oracle→Aurora migration

CloudRoute routes you to a vetted AWS partner who runs the SCT assessment, rewrites the hard PL/SQL, executes the DMS CDC cutover with a tested rollback, and scopes MAP funding. AWS funds qualifying migrations. No DIY conversion learning curve on your production database.

matched within< 24h
database TCO cut60–90%
migration cost (MAP)low / $0
Oracle to Aurora PostgreSQL: SCT + DMS Migration Guide · CloudRoute