Memory Tuning
createWorkbookStream() takes five options. Four of them control where temporary data lives and how strings are stored; protection sets workbook protection and does not affect memory. The defaults suit most exports; change them when memory is tight or there is no writable filesystem. For guidance with measured numbers, see Large Exports.
tempStorage
Controls where sheet data is spooled while rows are being committed.
| Value | Description |
|---|---|
"file" (default) | Each sheet's OOXML fragments are written to a temp file on disk. Disk I/O is the limiting factor, not RAM. |
"memory" | Fragments are held in memory buffers. Faster I/O but heap grows with total serialized XML size. |
Keep "file" unless the runtime has no writable filesystem. With "memory", memory grows with the size of the serialized sheet.
tempDirectory
When tempStorage: "file" is active, tempDirectory controls where the intermediate sheet spools are written.
Each workbook writes into its own private subfolder of that directory (created with owner-only permissions), so two exports can share one tempDirectory. The subfolder and its files are deleted when the export finishes, fails, or you call dispose(); the directory you pass is never removed.
import { createWorkbookStream } from "typed-xlsx";
const workbook = createWorkbookStream({
tempStorage: "file",
tempDirectory: "/tmp/typed-xlsx-spool",
});
import { createWorkbookStream } from "typed-xlsx";
// Large export: keep intermediate XML off the heap
const large = createWorkbookStream({ tempStorage: "file" });
// Small export running in a constrained environment where disk is slow
const small = createWorkbookStream({ tempStorage: "memory" });
memoryProfile
A convenience preset that picks a string-table strategy for you.
| Value | String mode | Trade-off |
|---|---|---|
"balanced" (default) | "shared" | Smaller output file, shared string table kept in heap |
"low-memory" | "inline" | No shared string table in heap, larger output file |
"compact-file" | "shared" | Same as balanced: optimizes for file size |
import { createWorkbookStream } from "typed-xlsx";
// Minimize heap: useful in memory-constrained environments (edge, Lambda)
const lowMem = createWorkbookStream({ memoryProfile: "low-memory" });
// Minimize output file size
const compact = createWorkbookStream({ memoryProfile: "compact-file" });
strings
Overrides memoryProfile and sets the string storage strategy directly.
| Value | Behavior |
|---|---|
"shared" | All string cells written to a shared string table (sharedStrings.xml). Excel deduplicates repeated strings: smaller file for data with many repeated values. |
"inline" | String values written inline in each cell element. No shared string table is built in memory. |
"auto" | Falls back to the memoryProfile preset. |
import { createWorkbookStream } from "typed-xlsx";
// Explicit shared strings: repeated string values (status, region, category) compress well
const sharedStrings = createWorkbookStream({ strings: "shared" });
// Explicit inline: no heap overhead for string deduplication
const inlineStrings = createWorkbookStream({ strings: "inline" });
When both memoryProfile and strings are set, strings takes precedence.
Combining options
For a large export in a memory-constrained environment:
import { createWorkbookStream } from "typed-xlsx";
const workbook = createWorkbookStream({
tempStorage: "file",
memoryProfile: "low-memory", // inline strings, no shared table in heap
});
For a medium export where file size matters more than memory:
import { createWorkbookStream } from "typed-xlsx";
const workbook = createWorkbookStream({
tempStorage: "memory", // fast I/O
strings: "shared", // deduplicate strings, smaller output
});
What stays in memory
Whatever the options, a stream export keeps:
- the batch being committed, until
commit()resolves - the style registry and summary accumulators, which are small
- the shared string table, with
strings: "shared" - merge ranges, hyperlinks and images, and the row ranges of summary formulas that read logical rows
With file spooling and inline strings, a flat export's memory barely grows with the row count: 274 MiB at 200k rows and 279 MiB at 500k in the benchmarks. Schemas that use the features in the last bullet grow more.