ANDREW/
MenuWriting
← Back to writing

TECHNOLOGY / ARTIFACTS / OFFLINE STARTUP

Downloaded. Still Available When Needed?

Andrew Yuan · Engineering experiment

A completed download is an event in the past

Imagine a team saying, “The file is ready. We already downloaded it.” The progress reached 100%, and the record says Success. When someone actually needs the file, it turns out to have been cleaned up.

The download record remains. The file does not. The system has not necessarily reported anything incorrectly: we have used an answer about a past event to answer a different question about the present.

I built Cacheweft as a local HTTPS artifact cache. An unprivileged local daemon and CLI manage downloads, checkpoint progress and verify content against an administrator’s trusted size and SHA-256 before publishing an immutable artifact. Immutability describes its managed-operation contract; it is not protection against malicious same-UID processes or root.

A successful download receipt beside an empty tray: downloaded, but still available when needed?
Concept illustration: a success receipt and an empty tray distinguish a historical event from current availability. It is not a product interface.

A successful request record answers whether that request completed. Whether the content is still available, and whether an application can start with it, need their own checks. That distinction also determines what an old request means after cleanup.

Connecting the cache to a service makes the startup contract explicit

In a controlled native macOS integration, I started the existing, unmodified tiny-batch-service HTTP inference service from a Cacheweft-managed Digits model. This is an application pilot, not evidence of external adoption or a new remote cache-management API.

An optional startup adapter in the repository uses the installed Cacheweft CLI. It waits for a successful request with available content, compares the result with the application’s trusted release digest, explicitly pins the artifact, materializes an application-owned model file and verifies that file. Only then does it start the existing service. The adapter is not part of Cacheweft’s runtime wheel.

These checks have different responsibilities. The administrator manifest defines the expected content the cache accepts. The application’s release digest identifies the version this startup requires. A successfully downloaded model is not enough if those expectations disagree.

When given a wrong release digest, the adapter refused to proceed before the inference service started. That is a property of this startup integration; Cacheweft does not independently select the right version for arbitrary applications.

Stop the source, then start a new service process

Cold startup downloaded and pinned the 9,890-byte Digits model, started the service and sent real HTTP inference requests for seven selected test rows. All seven responses matched independently generated reference probabilities within the declared tolerances.

The pilot then stopped the controlled HTTPS origin, restarted Cacheweft and started a fresh service worker. It loaded the same model digest. The seven responses matched again, with no additional recorded transfer attempts or accepted body bytes.

The fresh process matters. A worker that is already running may have loaded its model into memory. Continuing to answer requests does not independently show that the next startup can obtain that model.

The offline evidence is limited to the stopped controlled origin and the formal transfer counters. This pilot did not trace system calls or disconnect every network interface. It does not establish that every external dependency has been removed, or qualify arbitrary disconnected environments.

A pin protects content and leaves an operational responsibility

A successful download is not permanent retention. After explicit unpin and GC, the pilot reused the old successful request ID. The adapter refused to start the service because the content was unavailable. The historical result remained successful; it did not trigger another download or recreate the missing bytes.

On daemon restart, unfinished bounded requests become INTERRUPTED. Continuing them requires an explicit resume request with a new request ID and a fresh deadline. Reusing an old ID preserves its original outcome and deadline. Committed publication intents have a separate recovery path; not every restart state is an interrupted transfer.

A Cacheweft pin is a shared boolean, not a consumer lease or a reference count. The adapter leaves the pin set after exit or a later failure. Automatically unpinning when one process exits could remove protection that another user still needs.

That choice avoids treating one process’s exit as permission to release shared content. It also leaves work for operators: which versions are still needed, who can unpin them, and who revisits retention when pinned content prevents admission of a new artifact? Conservative retention can become a capacity problem if nobody owns retirement.

The application’s materialized model file sits outside cache accounting and GC. It needs its own lifecycle. Clearing the cache does not delete that copy or stop a service that has already loaded it. The old-ID test establishes that this adapter rejects the preparation state; it does not show that all consumers have lost every existing copy.

Three minutes and 360 requests remain bounded observations

The application integration and Linux VM resource observation are separate bodies of evidence. Together they do not form an end-to-end load test. The application pilot checks seven selected rows at each of two startups, not a complete accuracy evaluation or inference performance comparison.

A separate retained Linux VM closeout ran the installed systemd service for 180.016 seconds, completing 90 cycles and admitting 360 requests in the same process. Each cycle included download and reclamation, partial-transfer expiry followed by explicit resume, and cancellation. The 360 admitted requests are neither 360 successful downloads nor 360 inference calls.

The early RSS median covers seconds 30–60; the late median covers seconds 150–180. They were 26,193,920 and 26,275,840 bytes, an increase of 81,920 bytes, or 80 KiB. File-descriptor and thread medians stayed unchanged, as did the observed process and systemd invocation identities.

The run passed its fixed workload gates. It does not prove zero leaks or a long-term plateau. Retained request history still consumes metadata: GC reclaims payload, not history. This article cites existing records; preparing it did not rerun a VM, hardware test or application integration.

Turn “available offline” into acceptance conditions

Before deployment, I would name the supported version, startup path and retention responsibility together. Each of these four tested cases answers a different question. Passing one does not establish the others.

On a narrow screen, scroll the table horizontally to see every column.

Four checks between download completion and application startup
Tested conditionRecorded resultWhat it does not establish
Cold startup with the specified modelDownload, pin and startup completed; seven responses matched references.A complete accuracy or load qualification.
Source stopped, cache restarted, fresh worker startedSeven responses matched again; no extra transfer attempts or body bytes.Removal of all external dependencies.
Wrong application release digestThe adapter refused before starting inference.Publisher identity or model safety.
Old successful ID after explicit unpin and GCThe adapter refused startup because content was unavailable.Deletion of separate application-owned copies.

Someone also needs to maintain those conditions. Who approves the release digest? How long must a required version remain pinned? When the application retires, who removes its copy and coordinates unpinning? What is the executable response when request history or storage reaches its limit?

Keeping every version adds storage and management costs. Releasing one too early can prevent a new service from starting when the source is unavailable. Deployment owners need to make that trade-off explicitly; a successful-download indicator cannot make it for them.

Hashes, restart and offline operation have different boundaries

A matching hash establishes agreement with trusted expected bytes. It does not itself establish publisher identity, model safety or licensing. Obtaining and updating a trustworthy manifest remains a deployment responsibility.

This is a local service within a trusted-user scope. It does not isolate against malicious same-UID processes or root. Logical payload budgeting is not a filesystem quota, application copies are accounted for separately, and request and manifest histories are finite without automatic rollover.

Sudden power-loss recovery, systemd boot autostart and zero-gap boot availability have not been qualified by these records. A three-minute controlled workload and seven checks with a small model cannot establish long-term stability or large-model deployment guarantees.

Availability still needs an owner

For me, the useful result of this integration is a more testable version of “it should be there”: which release we need, whether the bytes remain available, whether a fresh service can use them, and who can decide that the version no longer needs protection.

The cache can preserve progress, verify content and refuse to mistake old success for current availability. Retention periods, application-copy lifecycles and retirement decisions still belong in the deployment and operating plan. Download completion is a past event. Relying on it later requires current evidence and someone responsible for keeping the required version available.

Sources and retained records

Code: Cacheweft on GitHub · MIT licensed. Evidence links are pinned to the reviewed revision; earlier measurements keep their original provenance.

Share this article