Skip to content
dply/edge

Apps & deployments

Builds

How dply clones, installs, and builds your repository, and the settings, limits, and caches that apply to every build.

Every deploy starts with a build. dply clones your repository at the commit being deployed, installs dependencies, runs your build command in an isolated container, and uploads the output directory to the edge. This page covers the build settings, how dply picks a Node version and package manager, the build cache, and the limits your plan sets on build time and concurrency.

Container apps build differently: dply builds a Docker image from your repository instead of running a Node build. See Container apps.

Build settings

In your app, open Build. The page opens with one sentence, such as "Every push to main on acme/web runs npm ci && npm run build and publishes dist/. The last 10 releases are kept for rollback." Below it, under How it builds, each setting is a row; click one to change it in a dialog and choose Save.

Row What it does Default
Deploy on push Whether a push to the production branch starts a deploy. See Deploy triggers & hooks. On
Build command The shell command that produces your site. Required, up to 500 characters. npm ci && npm run build
Output folder The folder, relative to the build folder, that dply uploads after the build. Required. dist
Repository root A subdirectory to build from, such as apps/web. See Monorepos. The whole repository
Unknown paths Serve index.html for unknown paths so client-side routers work, or return 404. Not shown for server-rendered or container apps. A change updates the live deployment immediately. Serve index.html
Releases to keep How many past deployments keep their files for rollback, from 1 to 50. Older deployments stay in the history but lose their files. 10
Deploy id in the footer Prints the live deployment id at the bottom of HTML pages. Off

Other settings apply to the next deploy, so redeploy afterwards: open Deploys and choose Redeploy the latest. The repository and branch are shown at the top of the list and can't be changed here.

A dply.yaml file in your repository can override the build command, output directory, and build root on every deploy. When it does, the row shows the file name in amber, the setting's dialog says what the file sets, and a row for the file lists its build keys and any warnings. See Configuration files.

Note

The repository and production branch are fixed when you create the app. To build from a different repository or branch, create a new app.

What a build does

Each build runs these steps, and the live log on Deploys shows each one as it happens:

  1. Clone. dply clones the repository at the commit being deployed, using your linked Git account for a private repository (the token never appears in the log). When a Repository root is set, only that folder and the workspace files it needs are checked out. See Source control.
  2. Read configuration. dply reads dply.yaml and wrangler.toml from the build directory. A dply.yaml that fails validation stops the build here.
  3. Restore the build cache. See Build cache below.
  4. Install and build. dply installs dependencies with the package manager your lockfile names, then runs your build command.
  5. Check the output. The output directory must exist and, for static and hybrid sites, contain an index.html at its root. The total output must be under 500 MB.
  6. Publish. dply uploads the output and switches traffic to the new deployment. See Deployments.

Node.js version

dply picks the Node.js version from your repository, checking these in order and using the first one it finds:

  1. engines.node in package.json
  2. .nvmrc
  3. .node-version
  4. packageManager in package.json (for example, pnpm@11 implies Node 22)

Supported versions are Node 18, 20, 22, and 24. With no version hint, dply uses Node 22. A few rules decide the final version:

  • An open-ended range such as >=18 builds on Node 22, not 18. Many starter templates declare >=18 while their dependencies need newer Node.
  • An odd-numbered release such as 21 rounds up to the next supported version (22).
  • A version below 18 builds on 18, and a version above 24 builds on 24.
  • lts/* aliases in .nvmrc are ignored.

The build log shows which version was chosen and why:

bash
[node] Detected Node 20 from .nvmrc ("20") — using node:20-bookworm

Note

Only the four sources above set the Node version. A node key under build: in dply.yaml, or a NODE_VERSION variable, has no effect.

Package managers

dply installs dependencies for you, based on the lockfile in the build directory:

Lockfile Install command
pnpm-lock.yaml pnpm install --frozen-lockfile, through Corepack, with a pnpm version matched to the Node version
yarn.lock yarn install --frozen-lockfile, through Corepack (the packageManager version when set, otherwise Yarn 4)
bun.lock or bun.lockb bun install --frozen-lockfile
package-lock.json npm ci
package.json only npm install

Because dply runs the install step itself, it adjusts your build command in three ways:

  • A leading install step, such as npm ci && or pnpm install &&, is removed so dependencies are not installed twice.
  • npm run and npm exec are rewritten to the detected package manager, so npm run build runs as pnpm run build in a pnpm repository.
  • --if-present is added to each run script.

Important

Because of --if-present, a missing build script does not fail the install step. The build fails later with Build output directory not found or Build output is missing index.html. If you see either error, check that the script named in your build command exists in package.json.

Hooks

Under Build → Hooks you can add commands that run around the build, one per line. Static, SSR and hybrid apps get Before the build (after dependencies install) and After the build (before publishing); they run in the same container and appear in the build log. Container apps get Release, which runs in the new version before it takes traffic, and After deploy, which runs once the deploy is live. See dply.yaml hooks to set them in your repository.

Environment variables during the build

The build container receives your production environment variables, the secrets linked to the app, any env.public values and build.env_files from dply.yaml, and variables from attached resources such as Realtime. Frameworks that inline variables at build time, like Vite's VITE_*, read them here. See Environment variables.

Build cache

dply caches dependencies and framework caches between builds of the same app:

  • node_modules and node_modules/.cache
  • .next/cache, .nuxt, .astro, .svelte-kit
  • dist/.cache

The cache key combines the Node version, the repository root, and your lockfile. When the lockfile changes, dply restores the newest cache built on the same Node version, and your package manager reconciles the difference. Each app keeps up to 500 MB of cache, and the oldest entries are removed first. The cache is saved after the deployment is published, so it does not slow the deploy down.

Separately, downloaded npm, pnpm, and Yarn packages are cached per organization, and each repository's Git history is kept between builds, so repeat clones fetch only new commits.

The cache never blocks a deploy. If a restore or save fails, the log records it and the build continues cold.

Note

There is no control to clear the build cache. A lockfile change starts a fresh cache key. To force a cold install, change the lockfile.

Limits

Build concurrency and timeout depend on your organization's plan:

Starter Pro Team
Sites Unlimited Unlimited Unlimited
Concurrent builds 1 2 5
Build timeout 20 min 45 min 60 min
Custom domains (per organization) 3 20 100
Container app instances 1 per app Autoscaling Autoscaling
Queue workers per app 1, starts when jobs arrive 5, autoscaling 10, autoscaling
SQL databases (D1) 2 10 50
Queues 2 10 50
Realtime connections per app 200 1,000 5,000
Audit log No No Yes
Meter Price Unit
Build time $0.0091 per minute, billed per second

Each plan includes build minutes every billing period: 300 on Starter, 1,000 on Pro and 3,000 on Team. Build time past that bills per second. See Plans & pricing.

How these work:

  • Build time is counted, per second, from the start of the clone to the end of the build. Time spent waiting in the queue and publishing is not counted. Failed builds count too.
  • Concurrency is per organization. When every slot is busy, the next build waits and its log shows Queued — waiting for an earlier build in this organization to finish.
  • Timeout stops a build that runs longer than your plan allows. The deploy fails and the live site keeps serving the previous deployment.
  • Superseded builds. Starting a new deploy of an app cancels any build of that app that is still running. When you push several commits quickly, only the newest one finishes.

Each build container also has fixed resources: 4 GB of memory, 2 CPUs, and a limit of 2,048 processes.

Build isolation

Your build runs code from your repository and your dependencies, so dply isolates it from the platform and from other customers:

  • Each build runs in its own container, as an unprivileged user, with all Linux capabilities dropped and privilege escalation blocked.
  • Builds run on a dedicated network, and cloud metadata hostnames resolve to nowhere.
  • Package download caches are separate for each organization, and the build cache is separate for each app, so one customer's build cannot change what another customer's build installs.
  • The build receives only your app's own environment variables and linked secrets.

For more on how dply separates customers, see Platform security & isolation.

Troubleshooting

Log message What to check
Build output directory not found: dist The Output folder does not match what your framework writes, or the build script did not run.
Build output is missing index.html at the root of: dist Point the Output folder at the folder that contains index.html, or use server rendering for apps without one.
Build artifacts exceed maximum allowed size. The output is over 500 MB. Move large media to object storage.
dply config lint failed: … Fix the listed errors in dply.yaml. See Configuration files.
Repository root "apps/web" was not found in the checkout. Correct the Repository root row on Build.

For more, see Troubleshooting builds.

Next steps

View as Markdown llms.txt

dply/edge