LockFlare

Both runtimes

Three constraints apply whichever runtime you use, and all three come from the same place: the application exists in memory and has no writable directory of its own on the host.

No writable application directory

There is no web root, no package directory and no build output on disk — so there is nowhere for the application to write next to itself. This is the property that removes web shells, dropped executables and path traversal as attack classes, and it is not configurable, because making it configurable would remove the guarantee.

In practice this affects applications that treat the local filesystem as storage:

PatternWhat to do instead
File uploads written to ./uploads Object storage — S3, R2, Azure Blob — or a database blob column.
SQLite or any file-backed local store A network database. A local database file has nowhere to live and would not survive a restart anyway.
Disk caches written at runtime In-memory caching, or Redis / Memcached.
Logs written to a file Write to stdout or stderr. The engine captures them, and they reach journalctl or PM2 like any service.
Generated files served back to users Generate in memory and stream the response, or write to object storage and redirect.
Most applications that write locally are doing it for convenience rather than necessity. The ones where it is genuinely structural — a media pipeline working on multi-gigabyte temporary files, for instance — are a poor fit, and it is better to know that on day one.

Everything served is memory-resident

Application code and static assets stay in memory for the life of the process. That is what removes disk from the serving path — and it means RAM is the resource to plan against, not storage.

On small artifacts this is negligible. On large ones — a big static bundle, a large dependency graph, many applications on one host — it becomes the dominant cost, and capacity should be sized for every served application being resident simultaneously.

If memory is already the binding constraint on your hosts, this architecture works against you rather than for you. Worth modelling before you commit rather than discovering after.

Build before you push

LockFlare serves the build you give it. It does not run your bundler, compiler or package manager, and there is no build step on the server — deliberately, because a build step would need a writable directory and a toolchain on a host that has neither.

Run npm run build, dotnet publish or whatever your pipeline does, then push. A stale dist/ deploys exactly as stale as it is.

Nothing about your build changes: same toolchain, same CI, same test suite, same review process. LockFlare consumes the output rather than replacing any part of it.

One entry point

Each project has a single starting file that the interpreter loads and runs. Applications structured around several independently-launched processes need to be either split into separate projects or given one entry point that starts what it needs.

Static assets are staged, and ephemeral

Where an application serves its own static assets, those are staged into a RAM-backed filesystem inside that application’s private mount namespace, for the life of the process only. It is volatile memory: invisible to the host and to every other application, never flushed to durable storage, and destroyed when the process exits.

The practical consequence is that anything written there is gone on restart. It is a serving mechanism, not storage.