NetSuite
Jul 21, 2026 · 3 min read

Why Your Aging Report Takes Four Minutes

Stale open invoices accumulate silently across migration debt and billing edge cases until they throttle month-end close and make your aging report unusable.

Why Your Aging Report Takes Four Minutes

How You Got Here

Migration debt accounts for the majority. Invoices loaded from a legacy system during go-live, often with a zero or penny balance, never closed because closing them wasn't in scope and nobody wanted to touch them once the migration was "done." They sit there. Accumulating across every search filter you didn't think to add.

Abandoned order flow adds more. A sales order gets partially fulfilled, partially billed, then the deal dies. The invoice stays open because the credit memo process wasn't followed, the rep moved on, or the customer was written off in the GL but not in A/R.

Billing edge cases fill in the rest: payment applications that didn't fully close due to rounding, currency revaluation residuals, transactions that hit billing before a discount was applied. Each one a fraction of a cent. Technically open. Thousands of them.

None of these feel urgent when there are ten. At a hundred thousand, your aging report takes four minutes to load. At a million plus, you are throttling month-end close.


The Wrong Way to Close Them

The instinct is to write a script that loops through a saved search result and calls voids each transaction or applies a zero-dollar credit memo. That instinct will get you into trouble.

Period locks bite first. If you are closing invoices that originated in locked periods, you are creating accounting entries in the current period that will not reconcile to anything. Revenue recognition schedules attached to those invoices may trigger on close. You may be releasing deferred revenue that was already handled another way.

The audit trail is the other trap. Mass-closing transactions with no documentation is an open invitation for a question you cannot answer: "Why did these close in March?" "Because we ran a script" is not an answer. You need a reversible record — a log that captures every transaction ID, its state before, what closed it, and who authorized it.

Do not void without understanding what voiding does to the GL in your account configuration. In some setups, void creates reversal journal entries. In others, it does not. The behavior is period-sensitive and not always what you expect.


The Safe Approach

Start with a saved search that returns only the invoices you are targeting. Be specific: balance less than a threshold you agree on with finance, transaction date before a cutoff, customer status, whatever segmentation makes sense. Do not write a script that grabs everything open.

Export that set to a staging table or a spreadsheet. This is your reversible record. Before anything closes, you know what was open. After, you know what changed. That list is your audit defense.

Close in batches. If you have SuiteScript doing this, batch at 50–100 records per scheduled script execution or, better, use a Map/Reduce script, which handles batching and governance natively; in a scheduled script, check remaining usage with N/runtime and reschedule with N/task. A mass operation running unconstrained in production will hit governance limits, fail mid-batch, and leave you with a partial state you have to reconcile. Throttle it. Let it take three days. The invoices have been open for three years — a few days does not matter.

Use credit memos, not voids, for anything with a GL impact. A zero-dollar credit memo applied to a zero-balance invoice closes it cleanly, leaves a clear audit trail, and does not create reversal entries. If the invoice has a real balance you are writing off, that requires finance sign-off and a formal write-off memo, not a script.

Build a dry-run mode into whatever you write. Log what would close without closing it. Run that against a sandbox with a production data refresh first. Validate the count and the GL impact. Then run production in batches.


Bottom Line

Stale open invoices are a performance problem, a reporting problem, and a reconciliation problem that compounds every month you leave it.

Closing them the wrong way trades one mess for a worse one.

The safe path is slower than you want. Batch it. Log everything. Get finance to sign off on the cutoff and the method before you touch production.

It is not exciting work. It is the kind of work that quietly makes everything else faster.

Dealing with this in your own NetSuite account?

We fix exactly these problems in production. Run a free read-only health scan, or talk to a senior NetSuite consultant who has seen it before.

Mike Pagani, founder of Adaptive Solutions Group

Written by Mike Pagani, founder of Adaptive Solutions Group — a NetSuite consultancy based in Pittsburgh, PA. Mike has been building SuiteScript automations, integrations, and NetSuite rescue projects since 2013.