By Dênio Flávio Garcia da Silva
I’ve spent a lot of time auditing APEX environments, and nothing sinalizes a maintenance nightmare quite like the “Hidden Item Explosion.” We’ve all been there: a simple form grows, logic accumulates, and suddenly you’re juggling dozens of values across multiple processes. It works, sure, but would you trust your future self to debug that six months from now? I once found 45 hidden items on a single page, in other words, a total maze that no one dared to touch.
At first, it’s straightforward: a button click triggers a PL/SQL block or an Invoke API. But things get messy when processes stop being isolated. Step A needs a value from Step B, which depends on Step C. Before you know it, you have an execution chain living inside your page processing.
From the field, I see this all the time. The application works, but the way values move is neither practical nor efficient. When outputs are scattered across the page state, understanding the flow becomes a mental puzzle. You’re forced to open every single process just to map out how data is being handed off.
The real challenge in APEX often isn’t triggering the process, it’s deciding how the output of one step becomes the input of the next. That is why we need to look beyond just adding “one more hidden item.”
The common starting point
A very common pattern in APEX is to associate a process with a button click and execute business logic from the Processing section of the page.
That process might:
- run a PL/SQL block directly
- call a package procedure
- invoke an API through a wrapper package
- validate data and prepare values for later steps
- return status, messages, identifiers, or structured output
This is one of those patterns that everybody who works with APEX long enough ends up using.
And honestly, that is not the problem.
The problem starts when the page is no longer just executing one isolated unit of work.
Processing section with multiple chained processes:

When a simple process becomes an execution chain
Let’s take a very practical example.
A user fills out a form and clicks a button to generate a quote. At first glance, that sounds like a single action. But behind that click, the page may actually need to do something like this:
- Validate and normalize the request
- Call a pricing API
- Expand the returned payload into line items
- Persist the final result in application tables
That is no longer “just a process.” That is an execution chain.
And in that chain, each step depends on state produced by the previous one.
The first process may return a normalized customer identifier.
The second may return a quote ID and a response payload.
The third may transform that payload into temporary rows.
The fourth may save everything into the database.
From a business perspective, the user clicked one button.
From a technical perspective, the page is orchestrating multiple dependent steps.
This is the point where page processing becomes more architectural than procedural.
The button that starts the flow and the submit behavior tied to the page process chain:

The first solution most of us use: hidden page items
In real projects, the most common way to pass values from one process to another is with hidden page items.
And to be clear, I do not think that is inherently wrong, in fact, I use this approach a lot.
If Process A produces a value that Process B needs right away, storing that value in session state through a hidden item is often the most practical option. It is simple, explicit, and fits naturally into the way APEX pages work.
For scalar values, hidden items are usually a very good fit.
Things like:
- generated identifiers
- status flags
- normalized codes
- tokens
- calculated totals
- short messages
- values required immediately by the next step
This is especially useful when working with Invoke API style processing, where input and output parameters need to be mapped cleanly, and where output values frequently become the input of a later process.
In these scenarios, hidden items are often the glue between one step and the next.
However we cannot assuming that hidden items are the best destination for every kind of output.
Input parameters and output parameters being mapped to page items:

The hidden items created to support the flow :

Where hidden items stop being enough
The real trouble starts when the nature of the data changes. Let’s be honest: a hidden item is perfect for a customer ID, but it’s a nightmare for twenty quote lines. Sure, you can technically stuff a massive JSON payload into a page item, but just because APEX allows it doesn’t mean it’s the best place for it. I’ve learned the hard way that just because a solution “works,” it doesn’t mean it’s maintainable.
Whenever I’m auditing a page, I pause and ask myself: Is this output really page state, or is it just temporary process state?
This distinction is a game-changer for your architecture. I usually start worrying when I see hidden items multiplying like rabbits, or when a process starts returning complex, repeating structures that don’t belong in a scalar field. If you find yourself mixing temporary “junk” logic with actual page data, or if you need a map and a compass just to reconstruct the execution chain in your head, you’ve hit the limit.
When the processing model gets that noisy, the question is no longer about if you can pass data through a hidden item. The better question is: “Where does this state actually belong?”
My Handoff Toolbox: How I actually decide
Once the flow gets complex, I stop looking at everything as “just data” and start thinking about lifespan. Where does this information live, and how long does it need to stay there? Here is how I break it down in my daily work:
- The Quick Handoff (Hidden Items): I’m not against hidden items, I use them every day. They are the perfect “glue” for short-lived, scalar values like a generated ID or a status flag that the very next process needs to consume. If it’s simple and immediate, don’t overengineer it.
- The Session Context (Application Items): I move to application items only when the data transcends the page. If I’m dealing with a Correlation ID or an environment setting that multiple pages need to know about, it belongs to the session, not the page. It’s about global context, not just avoiding clutter.
- Handling Datasets (Collections): This is my favorite “clean” alternative. When an API returns twenty rows of line items or a group of validation messages, stop trying to force that into a string. I use APEX_COLLECTION to store these temporary datasets. It keeps the page state clean and allows me to show the data in a report immediately without hitting the main tables yet.
- The Persistence Layer (Staging Tables): If the flow needs to be audited, resumed tomorrow, or survive a session timeout, I stop thinking about “passing values” and start thinking about persistence. For resumable workflows or complex integrations, a staging table is often the safest and most professional choice.
- The “Silent” Orchestration (Pure PL/SQL): This is an underrated move. Sometimes, the cleanest page is the one with fewer processes. If I can handle the orchestration inside a single, well-structured database package, I’ll do it. Why externalize every little step to the APEX Processing section if it only adds noise?
Once the flow becomes richer, I usually think in terms of the type and lifespan of the state I am dealing with.
Putting it into practice: The Quote Request Chain
To show you how this works in a real-world scenario, I built a demo app based on a Quote Request flow. It’s a classic example: the user clicks one button, but behind the scenes, we’re orchestrating a multi-step execution chain.
(You can grab the app and check the code on my GitHub: github.com/denioflavio/demo_quote)
Here’s how the state evolves through the processes:
- Validation & Normalization: We start by cleaning up the input (customer docs, zip codes). The outputs here are simple scalars, like a CUSTOMER_ID or a TRACE_ID. For this, Hidden Items are still my best friend. They are quick, easy to map, and do the job perfectly.
- The API Call: Next, we hit the pricing engine. We get back a Quote ID and a total amount (more hidden items), but we also get a raw JSON payload. This is the fork in the road. Do we stuff that JSON into a text area? Probably not.
- The “Collection” Shift: This is where it gets interesting. The API returns line items, taxes, and discounts. Instead of trying to manage this in page state, I expand that payload directly into an APEX Collection. Now, I can show a clean report to the user with all the quote details without having saved a single row to my main tables yet.
- Final Persistence: Only after everything is validated do we move the data from the Collection to the actual Database. The state is no longer temporary; it’s now official business data.
This progression is exactly why I like this demo. It proves that page processing isn’t just about clicking buttons, it’s about architecture. Each step in the chain demands a different handoff strategy.
The first process and its purpose:

The second process, with the input dependency on values created earlier:

This patterns repeats on the next 2 process, like shown in this diagram:

The Bottom Line: Choosing the Right Tool
At the end of the day, the goal isn’t to avoid hidden items or to force collections everywhere. The goal is to choose the simplest mechanism that fits the nature of the data you’re moving. If I could boil my decision process down to a single rule of thumb, it would be this:
- Hidden Items for quick, scalar handoffs.
- Collections for temporary, row-based data.
- Tables for anything that needs to survive a session or be audited.
- Pure PL/SQL when the orchestration adds more noise than value to the APEX interface.
In many Oracle APEX pages, the button is only the visible trigger; the real design lives behind it. It’s about how visible that state should be and how understandable the flow will remain six months from now when someone else (or your future self) needs to maintain it.
From the field, I can tell you: enterprise APEX development isn’t just about making things work, it’s about making things last.

Deixe um comentário