Im trying to find the limitations of all possible ways to export data-
Object Table
Constraint
Default(No filters)
Filtered(Data)
Filtered(Properties)
Filtered(Both)
Rightclick
CSV
-
10000
Filtered(Data)<=10000
Filtered(Properties)<=10000
Filtered(Both-10000)
Excel
UTC (timezone)
200000
Filtered(Data)<=200000
Filtered(Properties)<=200000
Filtered(Both-200000)
Other
10000
Filtered(Data)<=10000
Filtered(Properties)<=10000
Filtered(Both-10000)
Custom
Function Backed Export (using a “Button” onclick)
CSV
-
10k
Excel
-
10k
But when writing custom “function backed export”, I find it inconsistent. Sometimes Im able to export >10k and based on number of properties this may vary.
Currently we try to aggregate by groups and not be too granular with the export data to stay within 10k limit.
So, it would be great to know if there is a walkaround to this hard stop.
Hi @montes, thanks for your solution.
We have a customised way of doing this download. We let the user pick the properties from the object type, Also we allow them to filter the data based on a function. So on the filtered data and customised column selection; we want to download exact data that is finaly visible in the object table. Currently, I was able to do XLSX export. But with limited number of objects.
As the bottleneck/threshold/limit is “Workshop timeout” which is by default ~
Limit
Value
Bottleneck
Workshop execution timeout
~7 seconds
Object loading (rows.all() ≈ 0.67ms/row)
Workshop response payload
~8 MB base64
XLSX file size (≈ content-dependent bytes/cell)
Main problem :
Function → rows.all() → full objects in memory → XLSX → base64 string → Workshop HTTP response
↑ bottleneck 1 ↑ bottleneck 2 ↑ bottleneck 3
(timeout) (CPU/memory) (8MB payload)
The three bottlenecks you identified are correct. Since you already have custom column selection + function-based filtering, here’s what to do:
Short term, squeeze more rows out of the current approach:
After filtering, project down to only the selected properties beforerows.all(). Loading full objects and trimming after is what kills you on memory/time.
Avoid rows.all() if you can — use rows.take(n) in chunks if the function API allows it.
Real fix — go async:
Instead of Function → XLSX → Workshop response, do:
Action triggers a Transform/pipeline with the filter params + selected columns
Pipeline writes the XLSX to a file in Foundry
Workshop polls or shows a “ready” state, then serves a download link
No timeout, no 8MB cap, no row limit. The user waits a few extra seconds but gets everything.
The synchronous path (Function → base64 → Workshop) will always have a ceiling. The only way around all three bottlenecks at once is moving the heavy lifting out of the Workshop request cycle.
Felipe Montes
Development Advisor
Follow me @ linkedin.com/in/felipemontesl/ or GitHub: Brazillianerd