The single most common performance defect I find in inherited Generic Inquiries is a filter that looks like it restricts the query but actually runs after the data has already been fetched — client-side, in the browser's grid, rather than as a SQL WHERE clause on the server. It behaves identically to the user in a small dataset and catastrophically differently once the underlying table has real volume.
Conditions tab versus the grid's quick filter — not the same thing
Acumatica gives you two ways to narrow a GI's visible rows, and only one of them pushes down to the database:
- Conditions tab (Schema Builder / GI Designer's Conditions), including parameter-driven conditions — these compile into the GI's underlying BQL query and become part of the SQL sent to the database. The database only ever returns matching rows.
- Grid-level "Filter" / search-as-you-type on a loaded results grid — this operates on whatever page of rows is already in the browser (or triggers a fresh server request depending on the exact control and build, but never guarantees the same execution plan as a real Conditions-tab filter). Relying on this as your primary filtering strategy for a large table means the "unfiltered" query already ran before the user typed anything.
The only reliable way to confirm a filter is actually running server-side is to check the SQL text via the Request Profiler (SM205070) or equivalent tracing and see your filter value inside the WHERE clause. A filter that "looks like it works" because the grid displays the right rows can still be doing the narrowing client-side on data that was expensively fetched in full first.
Every parameter needs a matching Conditions-tab entry to actually filter anything
A parameter declared on the Parameters tab does nothing on its own — it is just a typed input with a default. It only becomes a filter once referenced inside a Conditions-tab entry with =[@ParamName]. I have inherited more than one GI where a parameter exists, looks configurable, and is entirely decorative because nothing on the Conditions tab actually references it — the GI always returns the full table, and the parameter is a UI element with no effect.
-- Broken: parameter exists, nothing references it. Filter is decorative.
Parameters tab: @FromDate (declared, has a default)
Conditions tab: (empty — no condition uses @FromDate)
-- Correct: parameter is actually wired into a SQL-pushed condition
Parameters tab: @FromDate (declared, has a default)
Conditions tab: ARInvoice.DocDate Greater or Equal =[@FromDate]
Filters that technically run server-side but still block indexes
Pushing a filter into the Conditions tab is necessary but not sufficient for real performance — a condition that wraps the indexed field itself in a function (a date-truncation, a string manipulation) can prevent the database from using an index on that column even though the WHERE clause is genuinely server-side. Prefer conditions that compare the raw field directly against a parameter or literal, and do any transformation on the parameter/literal side instead:
-- Can use an index on DocDate
ARInvoice.DocDate Greater or Equal =[@FromDate]
-- Cannot use an index — function wraps the column
Year(ARInvoice.DocDate) Equals 2026
Filter before you join where the relationship allows it
Where a condition can be expressed on the primary table before a join fans rows out (see the cross-table-joins piece), filtering early reduces both the join's work and the eventual row count — the query planner often handles this automatically, but explicit, correctly-typed conditions give it the best chance to.
Wrapping up
Real server-side filtering means a Conditions-tab entry that is actually referenced by a parameter, compiles into the SQL WHERE clause, and avoids wrapping the filtered column in a function. Verify with the request profiler rather than trusting that a filter "looks like it's working" — grid-level filtering on an already-fetched page will fool you every time until the table grows.
Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.