AL+

Language: RO (română) EN (English)

Email us: paul@alplustech.com

A Node package import does not establish file lifetime

Cloudflare Workers offers Node file APIs with distinct lifetimes. Check bundled files, request-local scratch space and persistence before moving packages.

Citiți articolul în română

A package can import successfully and still depend on files that will not exist when its next operation runs. Moving Node software to Cloudflare Workers therefore needs a review of file and process assumptions. Follow each file from creation to its last required reader, and decide where persistence belongs. API availability can remove adaptation work without establishing the storage lifetime the application expects.

Looking back from November 2026, Cloudflare published its Node compatibility recap and a broader developer-platform post on 25 September 2025. These posts describe a developing platform, not a universal promise of full Node parity. The filesystem announcement itself was dated 15 August 2025, before the September recap. Dating the recap as the API's first availability would misstate the chronology.

The September Node recap also describes temporary space shared across requests in a Durable Object, while explicitly denying persistence across restarts or deployments. That is a scoped announcement claim, not durable object storage. The analysis below concerns ordinary stateless Worker requests; a Durable Object migration needs its own version-specific review.

Three places imply three different contracts

The current official filesystem reference, consulted on 9 November 2026, describes a memory-based virtual filesystem. /bundle exposes bundled modules as read-only files. /tmp provides writable temporary space unique to a request. /dev exposes selected character devices, including /dev/null and /dev/zero. These are current documentation claims, separate from the dated 2025 announcement rather than evidence that every present detail existed on that day.

A bundled template can be a good fit for code expecting to open a file by path. Its required property is that the selected template accompanies the deployed version and can be read. That says nothing about writing changes back to the bundle. A package that loads defaults and later rewrites the same path has crossed from a read-only use into another storage contract.

Temporary space can support intermediate work within a request. An illustrative converter might create scratch files and consume them before returning its result. If another request is expected to read those files later, the design has crossed a lifetime boundary. Choosing an identical filename does not create shared state, and a successful write does not establish that the file survives a later request or deployment.

Device paths carry their own semantics. They are not places to retain an application artifact merely because they appear alongside other paths in a directory tree. Review why a dependency opens one, what it expects from reads or writes and whether the specific API is supported. The filesystem's familiar appearance is a convenience, not evidence of a conventional persistent server disk.

Compatibility has a date as well as a flag

The August 2025 changelog states that node:fs is available by default with nodejs_compat and a compatibility date of 2025-09-01 or later. For earlier dates it documents enable_nodejs_fs_module together with nodejs_compat; it also names disable_nodejs_fs_module. Those are the historical activation boundaries relevant to the announcement. The post explicitly says temporary files do not persist or share across requests or Workers.

Current Node compatibility documentation, read on 9 November 2026, adds a later boundary: compatibility dates from 2026-08-04 enable Node compatibility by default. That later default should not be projected into a 2025 configuration. Record the date and applicable flags when evaluating an existing Worker; merely saying that Node compatibility is enabled omits part of the contract.

The same current reference distinguishes native implementations from shims that permit imports but throw when methods are called. An import-only check consequently establishes very little about a package's actual execution. Trace the paths the application will invoke, including error handling and optional features. This article interprets the documented boundary without changing configuration, accessing tokens, deploying a Worker or running a filesystem experiment.

A request does not own a permanent process

The current explanation of how Workers works, consulted in November 2026, describes isolates and their possible eviction. It does not give an application a permanent process reserved for all later requests. Keeping a filename in a module variable cannot extend the documented lifetime of the file it names. A remembered path and a persistent artifact are separate properties.

Consider an illustrative two-step export. One request starts generating a report and a later request downloads it. If the report exists only in request-local temporary space, the second step has no persistence contract to rely on. A durable design would need an explicit storage destination, an identifier and a completion state understood by both steps. Which storage service fits depends on the application's access, consistency and retention needs; the filesystem API alone does not choose one.

Failure paths deserve the same review. A dependency may write a cache, lock file or recovery marker that seems incidental until a retry depends on it. Ask whether losing that file merely costs recomputation or changes correctness. A harmless scratch file and the only record of accepted customer work warrant different decisions. This is an architecture analysis, not a report of tested package compatibility or an implemented export service.

Stateless libraries have a simpler path

The strongest counterargument is a library that only reads bundled assets or uses temporary files entirely within one request. Its assumptions may already fit, so replacing every file API with a new abstraction would add unnecessary work. Evaluate the actual paths rather than rejecting a package because it mentions Node or uses the filesystem.

For custom software development, make the migration inventory describe the writer, reader and required lifetime of consequential files. Keep compatible stateless uses and assign persistent artifacts an explicit home. Accept a package after its important execution paths meet those contracts, with version and compatibility settings recorded. A successful import is useful preparation; the storage review determines whether the application can keep its promises after the request has ended.