When a server action closes over a property access, the whole root object is serialized and sent over the network, even if only one leaf value is needed.
Example
function Page() {
const config = getConfig() // large object, may contain non-serializable values
async function action() {
'use server'
return config.api.key // only this leaf is used
}
}
Currently the entire config object is captured:
const action = register(hoistedAction).bind(null, config)
export async function hoistedAction(config) {
'use server'
return config.api.key
}
This means:
- More data is serialized into the RSC payload than necessary
- If
config contains non-serializable values (functions, class instances, etc.), the action fails at runtime — even though config.api.key itself is a plain serializable value
Expected behavior
Only the accessed path should be captured, so the action works as long as the accessed value is serializable, regardless of the rest of the object.
For example, this could be achieved by binding only the needed subtree:
const action = register(hoistedAction).bind(null, { api: { key: config.api.key } })
export async function hoistedAction(config) {
'use server'
return config.api.key
}
Notes
Next.js already handles this correctly by tracking member access chains rather than just the root identifier.
use servervariable binding #1170When a server action closes over a property access, the whole root object is serialized and sent over the network, even if only one leaf value is needed.
Example
Currently the entire
configobject is captured:This means:
configcontains non-serializable values (functions, class instances, etc.), the action fails at runtime — even thoughconfig.api.keyitself is a plain serializable valueExpected behavior
Only the accessed path should be captured, so the action works as long as the accessed value is serializable, regardless of the rest of the object.
For example, this could be achieved by binding only the needed subtree:
Notes
Next.js already handles this correctly by tracking member access chains rather than just the root identifier.