How to run an AR aging report in NetSuite
How to run an AR aging report in NetSuite: the standard report's limits, the saved search and SuiteQL versions, and the traps that make the buckets wrong.
NetSuite's A/R Aging Summary report, in the Customers/Receivables report category, buckets open receivables by days overdue as of a date you choose. Set the as-of date, confirm whether it ages by due date or transaction date, and group by customer. For custom buckets, subsidiary splits or unapplied credits, build a transaction saved search instead.
Key takeaways
- The standard A/R Aging Summary answers 'who owes us what' in about ten seconds. It stops being enough the moment you need custom buckets, a subsidiary split, or the collector's name on each row.
- Aging by due date and aging by transaction date produce different buckets for the same invoices. Confirm which basis your report is using before anyone quotes a 90+ number.
- The aging report ages by transaction date; the GL AR balance moves by posting period. A March-dated invoice posted in April will make the two disagree, and neither is wrong.
- Filter on amount remaining, not on status. A partially paid invoice is still Open, and an unapplied credit memo has a balance too.
- A saved search with a CASE bucket formula reproduces the whole report in one row per transaction, which is the only version you can join to owner, sales rep or dunning stage.
You need an AR aging report in NetSuite, you need it before a 10am call, and the number you produce is going to be repeated to someone who will not check it. That is the actual job. NetSuite ships a report that does most of it, and three or four mechanics that will quietly make your buckets wrong if you don't know about them.
- AR aging report
- A list of open customer receivables grouped by how long each has been outstanding — typically Current, 1–30, 31–60, 61–90 and 90+ days. It answers two questions at once: how much is owed, and how much of it is late enough to worry about.
The standard A/R Aging report
NetSuite has two canned aging reports in the Customers/Receivables report category: A/R Aging Summary (one line per customer) and A/R Aging Detail (one line per open transaction). Both are real reports, both run in seconds, and for most Monday-morning purposes the Summary is the right answer.
- As-of date — the report re-ages open items as at the date you pick, so you can produce last month's aging today. It is not a snapshot that was stored at month end; it is recalculated from the current transaction data every time you run it.
- Aging basis — the buckets can be driven by due date or by transaction date. Due date is what collections wants. Transaction date is what some auditors ask for. They give different answers for the same ledger, so agree on one.
- Subsidiary and currency context — in OneWorld, what you see depends on the subsidiary context the report is run in and the currency you display. Consolidated views translate child-subsidiary balances at a rate, so a consolidated 90+ total is not the sum of the local-currency numbers you were shown last week.
- Customisation — you can change the number of aging periods and the days per period, add columns, and save the result as your own report. That covers a surprising amount of ground before you need a saved search.
Where the standard report runs out
The canned report is a reporting object, not a working list. Four things push teams off it, in roughly this order of frequency:
- 1.You need a field it doesn't carry. Collector, credit hold flag, sales rep, customer category, dunning stage, PO number, last promise-to-pay date. The aging report has a fixed field vocabulary; a transaction saved search has almost the whole record.
- 2.You need to act on rows. A saved search result can be sorted, mass-emailed, driven into a dashboard portlet and clicked straight through to the invoice. A report is something you read.
- 3.Your buckets aren't 30/60/90. If your terms are net 45, a 1–30 bucket mixes not-yet-due and late invoices together and the report stops meaning anything.
- 4.You need it to tie to the GL. The aging report is transaction-date driven. Your AR control account is posting-period driven. Reconciling those two takes a different query, covered further down.
Build the saved search version
This is the version worth owning. It reproduces the aging buckets from open transaction balances, one row per transaction, with any field you like attached. Six steps.
- 01
Start a transaction saved search
Transaction is the right search type — not Customer. You want one row per open document, and you want the due date, which lives on the transaction.
- 02
Filter by open balance, not by status
Set the criterion Amount Remaining is not equal to 0. Status filters catch people out: a part-paid invoice is still Open, and a fully applied one flips to Paid In Full at slightly different moments than you expect. Amount remaining is the balance itself, so it can't drift from reality.
- 03
Include every document type that carries an AR balance
Invoices, credit memos, and — if your team posts them — customer deposits and journals against the AR account. If you filter to Type = Invoice only, your total will be higher than the ledger by the value of every unapplied credit, which is the single most common reason an aging report and a customer statement disagree.
- 04
Keep it to one row per transaction
Add the criterion Main Line is true. Without it, a 40-line invoice contributes 40 rows and your total is nonsense. This is the mistake that produces an aging report ten times larger than the balance sheet.
- 05
Add the bucket formula
Add a Formula (Text) result column with a CASE expression over Days Overdue (below). Then add Amount Remaining as a Sum. Group by customer and bucket, or use the bucket as a summary column to get the classic grid.
- 06
Publish it to the people who work it
Save it, give the collections role access, and add it as a dashboard view for them. An aging report that lives in someone's export folder gets worked once a month; one on a dashboard gets worked daily.
CASE
WHEN {daysoverdue} <= 0 THEN 'Current'
WHEN {daysoverdue} <= 30 THEN '1-30'
WHEN {daysoverdue} <= 60 THEN '31-60'
WHEN {daysoverdue} <= 90 THEN '61-90'
ELSE '90+'
END| Trap | What it does to the number | Fix |
|---|---|---|
| Type = Invoice only | Overstates AR by every unapplied credit memo and customer deposit. A $180,000 total can be $164,000. | Include credit memos and deposits; let their negative balances net inside each customer. |
| Main Line not set | Multiplies the total by the average line count per invoice. | Add Main Line is true, or aggregate on a transaction-level field only. |
| Aging by transaction date | Every invoice looks later than it is by the length of your terms. Net-30 invoices paid on day 29 show in 1–30. | Age by due date for collections. Keep transaction-date aging for audit requests only. |
| Multi-currency amounts mixed | Sums foreign and base amounts into one meaningless column. | Pick one: Amount Remaining (base) for reporting, Amount Remaining (Foreign Currency) for talking to the customer. |
| Journals against the AR control account | Sit in the GL balance with no customer document to age, so aging is understated. | Include Journal in the type filter, and report journals with no entity separately — they usually shouldn't exist. |
| Intercompany receivables left in | Inflates AR and DSO with balances no one is going to chase. | Exclude intercompany customers by category, then state that exclusion on the report itself. |
Paste the amounts and days overdue from your export to get bucket mix, weighted average days overdue and a suggested reserve.
The SuiteQL version
If you're pulling aging into a spreadsheet, a warehouse or a script, SuiteQL is less fiddly than a saved search export because the bucket logic is visible in one place. Open balances live on the transaction record, so you don't need a line join at all:
SELECT
BUILTIN.DF(t.entity) AS customer,
BUILTIN.DF(t.type) AS doc_type,
t.tranid,
t.trandate,
t.duedate,
BUILTIN.DF(t.currency) AS currency,
t.foreignamountunpaid AS open_amount,
TRUNC(SYSDATE) - t.duedate AS days_overdue,
CASE
WHEN t.duedate IS NULL THEN 'No due date'
WHEN TRUNC(SYSDATE) - t.duedate <= 0 THEN 'Current'
WHEN TRUNC(SYSDATE) - t.duedate <= 30 THEN '1-30'
WHEN TRUNC(SYSDATE) - t.duedate <= 60 THEN '31-60'
WHEN TRUNC(SYSDATE) - t.duedate <= 90 THEN '61-90'
ELSE '90+'
END AS bucket
FROM transaction t
WHERE t.type IN ('CustInvc', 'CustCred', 'CustDep')
AND t.posting = 'T'
AND t.foreignamountunpaid <> 0
ORDER BY days_overdue DESCTwo things to know about that query. foreignamountunpaid is the transaction-currency balance, so a multi-currency ledger needs the base-currency equivalent or a conversion step before you total it. And credit memos usually have no due date, which is why they get their own bucket rather than silently landing in Current. If the formatting of these queries in your notes has decayed into one long line, run it through the SuiteQL formatter before you paste it into a ticket. More recipes in the same shape are collected in SuiteQL transaction queries.
Tying aging back to the AR control account
When the aging total and the balance sheet disagree, work from the GL side. The accounting lines are the authority, and they carry the posting period the aging report ignores:
SELECT
SUM(tal.debit) - SUM(tal.credit) AS ar_control_balance
FROM transactionaccountingline tal
JOIN transaction t ON t.id = tal.transaction
JOIN account a ON a.id = tal.account
WHERE a.accttype = 'AcctRec'
AND tal.posting = 'T'
AND t.trandate <= TO_DATE('2026-06-30', 'YYYY-MM-DD')Run it both ways — filtered on transaction date, then on posting period. The difference is your date-basis gap, and it is usually a handful of documents dated at the very end of a month. Anything left after that is journals with no customer, or a subsidiary you forgot was in scope.
How to read the result once you have it
An aging report is not a scoreboard, it's a work queue. Three habits get more cash in than any change to the report itself.
- Work by value inside each bucket, not oldest-first. Sorting oldest-first spends your best collector's morning on a $340 freight dispute. Sort descending by amount within 31–60 and 61–90 and the same hour recovers six figures.
- Separate late from disputed. A disputed invoice doesn't age, it stops. If more than about 5% of overdue value is in dispute, the fix is upstream in billing accuracy, not in collections effort — see what DSO actually measures for the levers that follow.
- Set the reserve from bucket loss rates, not a flat percentage of sales. Bucket-weighted reserves survive audit questions better; the bad debt reserve calculator does the weighting, and AR aging buckets explained covers why the boundaries are where they are.
- Track the mix, not the total. AR growing with sales is fine. The 90+ share creeping from 3% to 7% while the total is flat is the signal, and it shows up a month before DSO does — the DSO calculator will tell you what that costs in cash.
The version where you just ask
Everything above is twenty minutes of work the first time and five minutes every time after, assuming nobody changed the terms, added a subsidiary or started posting journals to AR. This is the class of question answers directly: ask "show me AR aging by bucket for the UK subsidiary as at 30 June, excluding intercompany" and get the number computed live from your own account, with the SuiteQL it ran printed underneath so you can check the definition instead of trusting it. Read-only by default, so nothing in the ledger moves.
Frequently asked questions
Where is the AR aging report in NetSuite?
Both aging reports sit in the Customers/Receivables report category: A/R Aging Summary for one row per customer and A/R Aging Detail for one row per open transaction. If neither appears in your Reports menu, it is a role permission rather than a missing feature — the reports require access to receivables reporting.
Why doesn't my NetSuite AR aging report match the balance sheet?
Usually two causes. The aging report ages by transaction date while the balance sheet moves by posting period, so month-end-dated documents posted into the next period fall on different sides. And journal entries booked straight to the AR control account have no customer document to age, so they never appear in the aging at all.
How do I add custom aging buckets in NetSuite?
On the standard report you can change the number of aging periods and the days per period in the report's customisation options. For boundaries tied to your own terms, build a transaction saved search with a Formula (Text) column containing a CASE expression over Days Overdue — that gives you any bucket scheme you like, including per-terms buckets.
Should an AR aging report include credit memos?
Yes. Unapplied credit memos and customer deposits are part of what the customer owes, and leaving them out overstates AR by their full value. Include them and let the negative balances net within each customer. If you need gross exposure for a credit decision, report the two columns separately rather than filtering credits out.
Can I run a NetSuite AR aging report as of a past date?
Yes — the standard aging reports re-age open items as at whatever date you enter. Be aware that this is recalculated from current data, not a stored snapshot, so a backdated payment applied last week will change what a 31 March aging looks like today compared with what you printed on 1 April.
What is the best SuiteQL query for AR aging?
Select from the transaction table where posting = 'T', type is in ('CustInvc','CustCred','CustDep') and foreignamountunpaid is not zero, then bucket on TRUNC(SYSDATE) − duedate with a CASE expression. No line join is needed because the open balance lives on the transaction. Convert currencies before summing across subsidiaries.
Calculators for this
Paste your open invoices with days overdue to get AR aging buckets, percentage mix, weighted average days overdue and a suggested bad debt reserve.
Calculate days sales outstanding from your AR and credit sales. See days beyond terms, cash tied up in receivables, and what each day of improvement is worth.
Size your bad debt reserve from ageing-bucket loss rates, see it as a percent of AR, and compare it against a flat percent-of-sales provision.
Calculate your collection effectiveness index from beginning AR, credit sales and ending receivables. See what you collected against what was collectable.
Keep reading
AR aging buckets explained: why 30/60/90, how to compute weighted average days overdue, and how to set a bad debt reserve from the bucket mix.
DSO explained plainly: the formula, the three variants people confuse, realistic benchmarks by industry, and the seven levers that actually move it.
Eight SuiteQL transaction queries you can run today: AR aging, open orders, revenue by customer, PO status, item margin — each with its assumptions stated.
Build a top customers by revenue report in NetSuite, and see why revenue, invoiced and collected give three different rankings of the same customers.