Brief for Executives
Most Oracle migrations fail not because data cannot be moved, but because critical business behavior was embedded in the database and quietly disappears during migration. Features such as PL/SQL packages, autonomous transactions, schedulers, and queuing systems often act as core parts of the application, not optional conveniences. When these features are removed or translated mechanically, systems continue to run but behave incorrectly.
Organizations that succeed treat Oracle migration as an application modernization effort, not a database-only project. This article explains where migrations usually break and why assessment and architectural refactoring — discussed in Part 1: Migrating Away from Oracle — are prerequisites for success.
Most Oracle migrations don’t fail during data transfer. Tables copy. Rows match. Dashboards light up. For a brief moment, everything looks successful.
Then the application starts behaving strangely.
Reports are subtly wrong. Background jobs stop firing. Performance collapses under load. Teams discover that the database was doing far more than storing data — it was quietly acting as an application runtime. This is the moment when an Oracle migration stops being a database project and becomes something else entirely.
This article is about that moment. It builds directly on the ideas introduced in Part 1: Migrating Away from Oracle, where the focus was on scope, tooling, and target platforms. It is not a list of features or a compatibility matrix. It is a description of what actually breaks when organizations leave Oracle and move to PostgreSQL-based platforms such as AlloyDB or Cloud SQL.
The Illusion of Compatibility
In Part 1, assessment tooling such as Database Migration Assessment was introduced as a way to surface risk early. This section explains why those risks often materialize only after the migration appears technically complete.
On paper, Oracle-to-PostgreSQL migrations look manageable. Both systems are relational. Both support transactions, indexes, views, and stored procedures. Tooling reinforces this optimism by showing high percentages of “automatically convertible” objects.
The illusion breaks when teams realize that compatibility at the SQL level does not imply compatibility at the behavioral level. Oracle databases often embed years of business logic, operational assumptions, and side effects that are invisible until they are removed.
The migration succeeds technically, but the system fails functionally.
Packages Were Not Just Code Containers
Oracle packages are frequently described as a syntactic convenience. In reality, they are one of Oracle’s most powerful — and dangerous — features.
Packages provide encapsulation, shared state, initialization logic, and controlled access to internal variables. Over time, many systems evolve so that packages become long-lived, stateful components that applications rely on implicitly.
PostgreSQL has no equivalent construct. Functions are stateless. Schemas provide namespacing, not encapsulation. When packages are translated into collections of standalone functions, the state disappears.
This is where migrations first crack. Code still compiles. Calls still succeed. But behavior changes. Cached values reset unexpectedly. Initialization logic no longer runs when assumed. Subtle ordering guarantees vanish.
Fixing this usually requires redesigning where state lives — often pushing it into application code or explicitly modeling it in tables. This is not a translation problem; it is an architectural one.
Autonomous Transactions: The Hidden Contract
Autonomous transactions are often used sparingly, which makes them easy to underestimate. Logging, auditing, and error handling frequently rely on them.
Oracle allows a block of code to commit independently of the caller’s transaction. PostgreSQL does not.
During migration, these constructs either fail to convert or are replaced with normal transactional logic. The result is rarely obvious at first. Error logs go missing. Audit records roll back. Side effects silently disappear.
The deeper issue is that autonomous transactions represent an implicit contract between the database and the application. Removing them changes failure semantics. Addressing this requires rethinking transaction boundaries, not just rewriting code.
The Scheduler Was Part of the Application
In many Oracle environments, DBMS_SCHEDULER is not a convenience — it is the backbone of system behavior. Jobs move data, clean tables, trigger downstream processes, and enforce timing guarantees.
When these jobs are removed, nothing replaces them automatically. PostgreSQL has basic scheduling options, but cloud-native platforms encourage external orchestration.
Teams often migrate schemas and data first, assuming scheduling can be “fixed later.” Later turns out to be painful. Business processes stall. Nightly batches stop running. Dependencies surface only after production traffic resumes.
Successful migrations treat scheduling as application logic and move it deliberately to systems like Cloud Scheduler, workflow engines, or dedicated job runners.
Queues, Pipelines, and Disguised Messaging Systems
Oracle Advanced Queuing is rarely used accidentally. When it exists, it usually underpins asynchronous workflows.
PostgreSQL does not offer an equivalent. What looks like a database feature turns out to be a messaging system embedded inside Oracle.
When AQ disappears, applications lose guarantees about delivery, ordering, and retry semantics. Replacing it typically involves external systems such as Pub/Sub or Kafka, which forces architectural decisions that were previously avoided.
This is often the point where teams realize they are not just migrating a database — they are untangling a distributed system that was hiding in plain sight.
Performance After the First Load Test
Initial benchmarks after migration often look promising. Simple queries are fast. Indexes work. Latency is low.
Problems emerge under realistic load. Queries that relied on Oracle-specific optimizations slow down. Execution plans change. Data types such as unbounded NUMERIC introduce overhead. Concurrency patterns behave differently.
These issues are solvable, but they require tuning with PostgreSQL’s mental model, not Oracle’s. Teams that treat performance as a post-migration problem tend to discover it too late.
What Tools Can — and Cannot — Do
Google’s migration tooling is strong. Database Migration Assessment surfaces risk. Database Migration Service automates conversion and replication. Gemini AI helps explain and translate legacy code.
What these tools cannot do is redesign an application architecture that evolved around Oracle’s feature set.
The most painful migration failures occur when teams mistake tooling progress for functional equivalence. Green checkmarks do not mean the system behaves the same way.
The Real Question to Ask
The most important question in an Oracle migration is not “Can we move the data?” It is:
What responsibilities has the database silently taken on over the years?
The more the answer includes scheduling, state management, messaging, and control flow, the less this is a database migration — and the more it is an application modernization effort.
Closing Thoughts
This article is the continuation of Migrating Away from Oracle. Where Part 1 focused on why re-platforming is necessary and how Google Cloud tooling supports it, this article focuses on what breaks when Oracle-specific behavior is removed.
Leaving Oracle is possible, and many organizations do it successfully. The ones that succeed understand what will break before it breaks.
They treat Oracle-specific features as architectural commitments, not implementation details. They budget time for refactoring. They involve application teams early. And they resist the temptation to declare success based on schema conversion alone.
In the end, migrating away from Oracle is less about replacing a database and more about deciding where your system’s intelligence truly belongs.