Skip to content

Growing Memory & Data Segments

A WebAssembly module starts with however many pages you declare in (memory N). But sometimes you need more memory at runtime — for example, when the user uploads a large file or your data grows beyond what you anticipated. The memory.grow instruction and the (data ...) segment cover these two related concerns: growing memory and pre-seeding it with static bytes.

memory.grow takes one i32 argument from the stack: the number of additional pages to allocate. It returns the previous size in pages, or -1 if the grow failed (e.g., out of memory or would exceed the declared maximum).

(module
(memory (export "mem") 1)
(func (export "grow") (param $pages i32) (result i32)
local.get $pages
memory.grow))

You can also grow memory from the JavaScript side using mem.grow(n):

const mem = instance.exports.mem;
const oldPages = mem.grow(1); // returns previous page count, or -1

This is the most important gotcha: when WebAssembly memory grows, the underlying ArrayBuffer is detached. Any Uint8Array, Int32Array, or other typed view that was constructed from the old buffer becomes empty and unusable. You must re-create all views from mem.buffer immediately after every grow.

let view = new Uint8Array(mem.buffer); // valid before grow
mem.grow(1);
// view is now detached — do NOT use it
view = new Uint8Array(mem.buffer); // re-create from fresh buffer

The (data ...) segment lets you embed static bytes directly in the module and have them written into memory automatically at instantiation time. This is how compiled languages initialise string literals and read-only tables.

(module
(memory (export "mem") 1)
(data (i32.const 0) "Hello")) ;; writes 5 UTF-8 bytes at offset 0

The bytes are copied from the module into memory before any function runs, so the data is available immediately when your first exported function is called.

The example below uses a (data ...) segment to write "Hi" at offset 0, grows memory by one page, re-creates the typed-array view after the grow, and checks that both the new size and the original data are correct.

WebAssembly
What does the memory.grow instruction return?
What happens to existing typed-array views when WebAssembly memory grows?
What does a (data (i32.const 0) "Hello") segment do?