Node.js, part 12: top-level await — when a module is its own init sequence
Part 12from the Node.js series · 24 parts in all
Before top-level await (Node 14.8), a module that needed data before it could export anything had exactly one shape: export a promise, and make every importer remember to await it. The pattern leaked into every consumer and every consumer could forget. Top-level await lets the module own its own readiness.
The difference, side by side
// Before: the module exports a promise; every caller must unwrap it,
// and every caller can forget.
export const configPromise = loadConfig();
// Afterwards: the module is not "ready" until this resolves.
import { loadConfig } from './config.js';
const config = await loadConfig(); // only legal in an ES module
export default config;
Importers see a module that has already initialised. That is genuinely simpler — and it moves the waiting somewhere you cannot see, which is the trade.
The rules that come with it
- ES modules only. CommonJS forbids it, which is one more reason
importis the modern default. - The wait propagates.
await import('./slow.js')does not resolve until that module's top-level await does, so one slow initialiser delays everything that imports it. - Sequential by accident. Two top-level awaits in a module run one after the other. If they are independent, that is a self-inflicted latency:
// Two round trips.
const users = await loadUsers();
const orders = await loadOrders();
// One round trip.
const [users, orders] = await Promise.all([loadUsers(), loadOrders()]);
When to reach for it
Genuinely once-per-process setup: read a config file, open a database pool, resolve a secret. Not for request-time data. And there is an operational hazard worth designing around: because node's module graph is a graph, the slowest top-level await gates the whole application start-up, and a failure there is a boot failure — which is fine, as long as it is deliberate and the error is legible. Next: turning a folder of packages into one repo without adding a framework.