# Forge Deploy limits

Status: source-of-truth limits for the current implementation. Provider
provisioning and a production release remain separate from these code limits.

Forge applies the narrowest of the repository request, the project's frozen
entitlement receipt, the Forge safety ceiling, and the provider ceiling. A
project entitlement can raise a product default, but it cannot bypass a
provider or safety ceiling.

## Configuration and source

| Input | Limit |
| --- | ---: |
| `forgeBuild.ts` source | 64 KiB |
| Root `.forge/assets.json` source | 64 KiB |
| `.forge/assets.json` entries | 1,000 |
| Forge asset literal path | 1,024 UTF-8 bytes |
| Configuration syntax tree | 10,000 nodes |
| Literal nesting | 64 levels |
| Normalized configuration | 256 KiB |
| Wrangler TOML | 1 MiB |
| Generic Forge application bundle | 5 MiB |
| Raw OpenNext compiler-input entries | 150,000 |
| Raw OpenNext compiler-input files | 125,000 |
| Raw OpenNext compiler-input symlinks | 20,000 contained links |
| Raw OpenNext compiler-input file | 256 MiB |
| Raw OpenNext compiler-input total | 2 GiB |
| Raw OpenNext compiler-input path | 1,024 UTF-8 bytes |

Paths must be normalized repository-relative paths. Forge rejects path
traversal, special files, duplicate output paths, and output that changes while
it is inspected. Raw OpenNext compiler input may contain ordinary pnpm
symlinks only when every link resolves inside `.open-next`; published assets,
cache objects, and compiled modules remain regular files.

## Forge Assets and Git LFS

| Input | Limit |
| --- | ---: |
| Git LFS batch request | 100 objects, 256 KiB request body |
| Signed LFS upload and verify transfer | 12,000 operations per hour |
| Forge asset object identity | account entitlement, at most 1 GiB |
| Initial Worker-mediated basic transfer | 100 MiB per request |
| Transfer action lifetime | 5 minutes |
| Default migration suggestion: project `public/**` tree | aggregate strictly greater than 50 MiB |
| Default migration suggestion: other file | individual file strictly greater than 5 MiB |
| Adoption inspection | 100,000 repository files, 1 GiB proposed unmanaged bytes |
| Adoption apply | 9,998 selected files |

Migration thresholds are fixed in the current v1 inspection policy and affect
suggestions only. Administrators may include or exclude returned entries. The
thresholds do not raise an account entitlement, transport bound, build bound,
or publication limit.

The Batch endpoint remains bounded to 100 objects and a 256 KiB request. Each
short-lived signed object upload and signed verification request consumes the
separate 12,000-operations-per-hour LFS transfer budget, not the ordinary Git
mutation budget. Clients resume safely by rebatching the same OIDs: Forge
returns transfer actions only where work remains, and repeated verified-object
requests are idempotent. Ticket lifetime and byte ceilings still apply.

The 1 GiB object value is a Forge safety ceiling. Logical object bytes count
against every account authorized to reach that digest even when immutable
physical storage is reused. The effective object limit is the narrowest
account entitlement, repository policy, Forge ceiling, and active transport
ceiling.

The initial Worker-mediated basic upload is capped at 100 MiB, within
Cloudflare's single-request body limit for the current Worker plan. A resumable
or multipart transport is required before Forge can transfer larger individual
objects up to the 1 GiB identity ceiling. Rebatching resumes a set of bounded
objects; it does not split one oversized object into smaller request bodies.

## Connected Cloudflare publication

| Artifact | Limit |
| --- | ---: |
| Generated ESM entrypoint | 25 MiB |
| WebAssembly module | 10 MiB each |
| All WebAssembly modules | 25 MiB |
| Asset path | 512 UTF-8 bytes |
| Asset | 25 MiB each |
| Assets per release | 100,000 files |
| Assets per release | entitlement-driven, at most 1 GiB |

The planned AIE entitlement is 1 GiB of connected assets per release and must
be provisioned separately before migration. It does not raise Cloudflare's
25 MiB per-file ceiling or the 100,000-file provider ceiling. Forge counts
streamed bytes and stops before publication when any bound is crossed. Large
Forge Assets are represented by their verified content digest while the
manifest is planned; provider-requested bodies are checksum-fenced and
uploaded as raw single-asset streams with concurrency 3 when Cloudflare's
signed upload-session token advertises `wrangler_single_asset_uploads`. The
legacy capability fallback base64-encodes each provider bucket through a
backpressured multipart stream. The aggregate release entitlement therefore
does not require the runner to buffer the aggregate release bytes. During a
long raw upload, Forge retains the provider-operation fence with a 30-second
heartbeat and also renews it every 10 completed files.

## OpenNext output

| OpenNext output | Limit |
| --- | ---: |
| Compiled Worker modules | 2,000 files, 64 MiB each, 64 MiB total |
| Static assets | 100,000 files, 25 MiB each, 1 GiB total |
| ISR cache seed | 20,000 files, 25 MiB each, 250 MiB total |
| Compressed Worker | 10 MiB gzip |
| ISR trusted-ingest seed | 25 MiB each, 250 MiB total |

Raw `.open-next` is bounded compiler input, not a provider module graph. After
the credential-free Wrangler compile, Forge applies module and compressed-size
limits to the generated graph, and static-asset limits to the compiled asset
set. Cache seed limits remain separate. The smaller project entitlement still
wins. Within those limits, Forge seeds at most four ISR objects and 32 MiB of
source bytes in one provider batch. These are fixed trusted-runner memory and
request-concurrency ceilings, not repository-configurable entitlements.
Provider-version requests use buffered JSON below an 8 MiB compiled
entrypoint and switch to a backpressured raw-module multipart stream at 8 MiB or above.
The transport choice does not change artifact identity or provider limits; it
keeps large valid Workers from requiring duplicate module, base64, and JSON
allocations in the trusted runner. OpenNext packaging never collects the
compiled entrypoint into the runner isolate: the sandbox validates UTF-8,
SHA-256, byte size, and compressed size, and Forge later revalidates and
streams the same quiesced file for publication.

## What an operator may change

An operator may provision a reviewed project entitlement, provider target, or
approved zone. An operator must not edit a historical release receipt to make
an existing artifact appear eligible. Entitlement, source, adapter, Wrangler,
binding generation, module graph, assets, and cache seed all participate in
the immutable artifact identity.
