PL/SQL25 min readBy Priyanshu Pandey

PL/SQL Masterclass: Oracle Advanced Queuing (AQ) Architecture

Build robust, asynchronous, event-driven architectures natively within Oracle using Advanced Queuing (AQ). Learn how to enqueue, dequeue, and trigger events.

Architecture Guide · PL/SQL Masterclass

Advanced Queuing: Native Event-Driven Architecture

Don't build external Kafka or RabbitMQ clusters just to decouple your database transactions. Oracle Advanced Queuing (AQ) provides rock-solid, transactional messaging directly inside the database.

25 min read📅August 7, 2026✍️Priyanshu Pandey📚PL/SQL Masterclass

The Need for Asynchronous Processing

Imagine a retail application where a user clicks "Checkout". The database needs to:

  1. Update the inventory tables.
  2. Generate an invoice PDF.
  3. Send a confirmation email.
  4. Notify the warehouse shipping system.

If you write this synchronously, the user will be staring at a loading spinner for 30 seconds. If the email server is down, the entire transaction rolls back, and they lose their cart.

This is where Asynchronous Event-Driven Architecture shines. The user clicks "Checkout", you update the inventory, and then you Enqueue a message saying "Order 1234 Placed." The user gets an instant response. In the background, independent background workers Dequeue the message, send the email, and notify the warehouse.

While modern devs use Kafka or RabbitMQ, Oracle provides this exact functionality natively via Advanced Queuing (AQ). Because AQ is built into Oracle, messages are part of the standard database transaction—if your inventory update rolls back, the message rollbacks too!

Implementation

Step 1: Setting up the Queue

First, define the Payload (what data does the message hold?).

1. Create the Payload Object Type
PL/SQL
CREATE OR REPLACE TYPE order_msg_type AS OBJECT (
  order_id   NUMBER,
  customer   VARCHAR2(100),
  total_amt  NUMBER
);
/

Next, use DBMS_AQADM to create the Queue Table and the Queue itself, then start it.

PL/SQL
BEGIN
  -- 2. Create the physical storage table for the queue
  DBMS_AQADM.CREATE_QUEUE_TABLE(
    queue_table        => 'order_queue_tbl',
    queue_payload_type => 'order_msg_type'
  );

  -- 3. Create the Queue referencing the table
  DBMS_AQADM.CREATE_QUEUE(
    queue_name  => 'order_queue',
    queue_table => 'order_queue_tbl'
  );

  -- 4. Start the queue so it can receive messages
  DBMS_AQADM.START_QUEUE(queue_name => 'order_queue');
END;
/

Step 2: Enqueuing Messages (Producer)

When the user checks out, you enqueue the message using DBMS_AQ.ENQUEUE.

PL/SQL
DECLARE
  v_enqueue_options    DBMS_AQ.enqueue_options_t;
  v_message_properties DBMS_AQ.message_properties_t;
  v_message_handle     RAW(16);
  v_payload            order_msg_type;
BEGIN
  -- Instantiate the payload
  v_payload := order_msg_type(1001, 'Alice', 250.00);

  DBMS_AQ.ENQUEUE(
    queue_name         => 'order_queue',
    enqueue_options    => v_enqueue_options,
    message_properties => v_message_properties,
    payload            => v_payload,
    msgid              => v_message_handle
  );
  
  -- The message is NOT visible to consumers until you commit!
  COMMIT;
END;
/

Step 3: Dequeuing Messages (Consumer)

A background job can poll the queue using DBMS_AQ.DEQUEUE.

PL/SQL
DECLARE
  v_dequeue_options    DBMS_AQ.dequeue_options_t;
  v_message_properties DBMS_AQ.message_properties_t;
  v_message_handle     RAW(16);
  v_payload            order_msg_type;
BEGIN
  -- Wait up to 10 seconds for a message
  v_dequeue_options.wait := 10; 

  DBMS_AQ.DEQUEUE(
    queue_name         => 'order_queue',
    dequeue_options    => v_dequeue_options,
    message_properties => v_message_properties,
    payload            => v_payload,
    msgid              => v_message_handle
  );

  -- Process the message!
  DBMS_OUTPUT.PUT_LINE('Processing Order: ' || v_payload.order_id);
  
  -- Removing the message from the queue requires a commit
  COMMIT;
END;
/

Automated Consumer Callbacks

Constantly polling a queue with a WHILE loop wastes CPU. Instead, you can register a PL/SQL Callback Procedure. Oracle will automatically invoke your procedure the moment a message hits the queue!

You use DBMS_AQ.REGISTER to bind a procedure to a queue, creating a truly event-driven, push-based architecture without external infrastructure.

Common Gotchas

Important Gotchas

  • !

    ENQUEUE and DEQUEUE are standard DML operations. If you enqueue a message but forget to COMMIT, the consumer will never see it. If you dequeue a message and the consumer crashes before the COMMIT, the message rolls back onto the queue to be processed again.

  • !

    If a message constantly crashes the consumer, it will continuously roll back onto the queue, blocking all other messages. Configure a RETRY_COUNT on your queue to automatically move failing messages to an Exception Queue.

Key Takeaways

Key Takeaways

  • Advanced Queuing (AQ) decouples transactions, improving response times for users.
  • Because AQ is native, message enqueuing participates in your database transactions, ensuring absolute consistency.
  • Use DBMS_AQADM for admin tasks (creating tables) and DBMS_AQ for operational tasks (enq/deq).
RetailCoder
All systems operational
v1.0 Live

RC:OMS

Multi-channel order management with double-entry inventory ledger. Amazon, Flipkart, Shopify, WooCommerce — one source of truth.

Launch demo →
v1.0 Live

RC:Storefront

Self-hosted headless e-commerce. Your server, your data, zero transaction fees. Native RC:OMS inventory sync.

Visit Storefront →
Pipeline

RC:Pulse

AI-powered retail analytics and demand forecasting — built natively on top of your RC:OMS and Storefront data.

Request early access →
Built in India 🇮🇳  ·  Architected by Priyanshu PandeyTalk to an engineer →