Skip to main content

Command Palette

Search for a command to run...

How I Stopped Rebuilding Audit Logging on Every Oracle APEX Project

A production pattern I now deploy in under 30 minutes — and why I finally packaged it.

Updated
5 min read

🇪🇸 Leer en Español

In 2019, at 2 AM, I sat staring at an empty Oracle APEX log table while a furious project manager demanded to know why the billing system had just rolled back $40,000 in transactions. There was no stack trace. No payload. No context. Just a generic "ORA-06512" error.

That night cost us six hours of database archaeology. The worst part? I had built the audit logging system for that application myself, from scratch, just three weeks prior.

For most of my 9 years developing in Oracle APEX, I repeated this mistake. Every new project started the same way: a blank file, a quick package write, a slightly different table structure, and a different set of assumptions about commits. Every handoff was painful, and every debug session was archaeological.

In this APEX Insight, I outline the pattern that finally stopped this cycle: an opinionated, production-ready logging foundation that deploys in under 30 minutes.

The Cost of "I'll Just Write It Myself"

When starting a new APEX project, audit logging feels like a solved problem. It is not complex. Writing a package and inserting a row is straightforward. So developers build it quickly and move on to the business features.

Any developer can write a basic insert statement. The real difficulty begins six months later when:

  • A client asks who changed a specific record on Tuesday.

  • A bug surfaces in production and the error log has three fields instead of eight.

  • A new team member joins and has to reverse-engineer a custom logging convention before touching the code.

  • You start a new project and copy-paste from the last one—except the last one had a subtle flaw you never got around to fixing.

The real cost is not writing the logger. It is writing it differently every single time.

What a Production-Ready Pattern Actually Looks Like

After years of iteration across real enterprise projects, I settled on two packages that I now treat as non-negotiable infrastructure on every APEX application.

APP_AUDIT handles user action tracking:

APP_AUDIT.log_event(
    p_action     => 'UPDATE',
    p_table_name => 'EMPLOYEES',
    p_record_id  => :P1_EMP_ID,
    p_details    => 'Salary updated'
);

One call. It logs who, what, when, and where—including the APEX session context automatically. There is no complex UI or heavy abstraction layer to learn. Just a queryable table and a clean API.

APP_ERROR handles technical failures:

BEGIN
    -- business logic here
EXCEPTION
    WHEN OTHERS THEN
        APP_ERROR.log_error(
            p_context  => 'process_payroll',
            p_message  => SQLERRM,
            p_payload  => l_json_context
        );
END;

It captures the stack trace and accepts a JSON payload for contextual data. More importantly, it is designed to work with or without explicit commits—a detail that matters when a transaction rolls back and threatens to wipe out your error logs.

The Decisions That Aren't Obvious

Two design choices took me years to get right:

1. Autonomous Transactions in Error Logging

Your error logger must use PRAGMA AUTONOMOUS_TRANSACTION. If it does not and your main transaction rolls back, the error record is lost. You end up debugging blind. This sounds obvious in retrospect, but it is easily overlooked when writing a logger late at night before a production release.

2. Opinionated Defaults Beat Flexible Configurations

I spent too much time trying to make logging configurable—toggling columns and making fields optional. The result was a complex system that developers used inconsistently. The version that works in production is the one that makes decisions for you and enforces them everywhere.

Packaging the Foundation

Deploying variations of these patterns across dozens of projects shifted my perspective: logging is not code you write, it is infrastructure you install.

So I packaged it. The bundle includes clean SQL scripts, clear installation instructions, a commercial license for client projects, and comprehensive documentation to allow independent installation.

If you are an APEX consultant or developer shipping multiple applications, this foundation pays for itself the first time you avoid rebuilding it.

The bundle is available here: APEX Foundations Bundle

The single template is $39 USD, and both are available for $69 USD. You own the code with no recurring subscriptions.


Stop Rebuilding the Foundation

Audit logging and error handling are solved problems. The only question is whether you solve them once, correctly, or solve them repeatedly and inconsistently.

If you are starting a new APEX project this month, drop in a foundation that works and focus your time on the parts that actually differentiate your application.


Support the APEX Insights Project

If you found this APEX Insight helpful, consider supporting the project to help keep creating open-source demos, utilities, and expert content for the Oracle APEX community:

  1. GitHub Sponsors — For monthly contributions.

  2. Buy Me a Coffee — For a one-time support.


Connect and Learn

  • Subscribe to Newsletter — Get deep technical breakdowns and guides delivered directly to your inbox.

  • Follow on X — Quick tips, project updates, and real-time discussion.

  • Connect on LinkedIn — Daily APEX insights, architectural patterns, and engineering tips.


References

  1. Oracle Database PL/SQL Language Reference

    • Official documentation on PRAGMA AUTONOMOUS_TRANSACTION and exception block handling.
  2. Oracle APEX API Reference - APEX_SESSION

    • Guidance on utilizing standard APIs to access session parameters and contexts in background layers.

P.S. The next time you get a 2 AM call about a production failure, you can either spend six hours parsing raw SQL logs or open a structured JSON payload that tells you exactly who, what, and why. The choice is yours. The production-ready template is available right here.