Astro is a static site generator optimized for performance, but when your site grows to hundreds of pages or uses heavy integrations (React, Vue, Tailwind), builds can take 2-3 minutes. Most of that time is spent installing dependencies, not generating pages. PandaStack caches node_modules between builds, cutting install time from 90 seconds to under 10 on subsequent deploys.
This post shows how to deploy an Astro site to PandaStack, how the build cache works, and how to verify it's speeding up your builds.
A minimal Astro site
Start with a fresh Astro project:
npm create astro@latest
cd my-astro-site
npm installRun the dev server:
npm run devBuild the static site:
npm run buildAstro generates a dist/ directory containing the static HTML, CSS, and JS. This is what you deploy to the CDN.
Deploying to PandaStack
Create a pandastack.json at the repo root:
{
"type": "static",
"language": "nodejs",
"buildCommand": "npm run build",
"outputDir": "dist"
}Push the repo to GitHub, then deploy via the API:
curl -X POST https://api.pandastack.io/v1/projects \
-H "Authorization: Bearer psk_live_your_token" \
-H "Content-Type: application/json" \
-d '{
"slug": "static",
"name": "astro-site",
"repositoryName": "yourusername/astro-site",
"branch": "main",
"autoDeploy": true
}'The build runs, the dist/ directory is uploaded to the CDN, and you get a live URL like https://astro-site-xyz.pandastack.app.
Alternatively, use the deploy button:
[](https://dashboard.pandastack.io/deploy?repo=yourusername/astro-site&type=static)How build caching works
PandaStack runs builds in ephemeral Kubernetes Job pods. After the first build, the builder archives node_modules/ and uploads it to Google Artifact Registry. On the next build:
- 1The builder downloads the cached
node_modules.tar.gz - 2Extracts it to the build directory
- 3Runs
npm install(which detects the cache and skips unchanged packages) - 4Runs
npm run build
If package-lock.json hasn't changed, npm install completes in under 10 seconds instead of 90. The build time drops from 2 minutes to under 40 seconds—most of the remaining time is Astro generating pages.
The cache is project-specific and branch-specific. Deploying a different branch starts with a cold cache. Changing package-lock.json invalidates the cache, and the next build reinstalls all dependencies.
Verifying the cache is active
Check the build logs in the dashboard (Logs tab). The first build shows:
Installing dependencies...
npm install
...
added 1234 packages in 87sThe second build (same package-lock.json) shows:
Restoring cached dependencies...
npm install
...
up to date, audited 1234 packages in 8sThe "Restoring cached dependencies" line confirms the cache was used. If you don't see this, the cache may be disabled or the package-lock.json changed between builds.
Forcing a fresh build
If you suspect the cache is stale (e.g., a package updated but the lock file didn't change), clear the cache in the dashboard:
Project Settings → Clear Build Cache
The next build reinstalls all dependencies from scratch and rebuilds the cache.
Package manager support
PandaStack detects the package manager from the lock file:
package-lock.json→ npmpnpm-lock.yaml→ pnpmyarn.lock→ yarnbun.lockb→ bun
Caching works for all four. Pnpm and Yarn have built-in caching mechanisms, so the cache is especially effective with those.
If you're using pnpm and want to override the install command (e.g., to skip optional dependencies), set it in pandastack.json:
{
"type": "static",
"buildCommand": "pnpm install --frozen-lockfile && pnpm run build",
"outputDir": "dist"
}But the default auto-detection is usually sufficient.
When caching doesn't help
The build cache only speeds up dependency installation. If your build is slow because:
- Astro is generating 10,000 pages
- You're compiling Tailwind CSS with a massive config
- You're processing large images with Sharp
Then caching node_modules won't help much. The install step is already fast (10 seconds), and the slow part is page generation. In that case, optimize the build itself—enable Astro's experimental build caching, reduce the number of generated pages, or use a faster image processor.
Comparing build times
Here's a real example from an Astro blog with 200 pages and React integration:
| Build | Install time | Build time | Total |
|---|---|---|---|
| First (cold cache) | 87s | 54s | 141s |
| Second (warm cache) | 9s | 54s | 63s |
| Third (warm cache, no code changes) | 9s | 54s | 63s |
Caching cuts total build time by 55%. The install step drops from 87s to 9s, while the build step (page generation) stays constant at 54s.
For a Next.js static export with a similar page count, the improvement is even larger because Next.js has more dependencies.
Why this matters
Netlify, Vercel, and Cloudflare Pages all cache dependencies between builds, but they don't document how it works or give you manual cache invalidation. PandaStack's cache is explicit: you see "Restoring cached dependencies" in the logs, and you can clear it if needed.
The free tier includes 300 build pipeline minutes per month. With caching, a 2-minute build becomes a 1-minute build, effectively doubling your build quota. Paid plans increase the quota to 1000+ minutes, but caching reduces the need to upgrade.
Multi-framework support
The same caching logic works for any framework that uses node_modules:
- Astro, Next.js, Nuxt, Gatsby (static site generators)
- Vite, Parcel, Webpack (bundlers)
- React, Vue, Svelte (component frameworks)
The only requirement is that the build installs dependencies before running npm run build. If you're using a custom build script that skips npm install, the cache won't help.
Deploy button with caching
The deploy button automatically benefits from caching. No additional config needed:
[](https://dashboard.pandastack.io/deploy?repo=yourusername/astro-site)The first user to click it gets a cold build (90 seconds). The second user (if they deploy the same commit) gets a warm build (10 seconds). This makes open-source starters and templates deploy faster for everyone.
Common issues
Cache not restored: Verify package-lock.json exists and is committed to the repo. If it's missing, npm generates a new one on every build, invalidating the cache.
Install still slow: Check the logs for errors like "peer dependency warnings" or "postinstall scripts". Some packages run slow postinstall hooks that can't be cached.
Build fails after clearing cache: The cache may have hidden a dependency issue (e.g., a package that's installed but not in package.json). Fix the dependency and rebuild.
Full example repo
package.json:
{
"name": "astro-site",
"scripts": {
"dev": "astro dev",
"build": "astro build"
},
"dependencies": {
"astro": "^4.0.0"
}
}pandastack.json:
{
"type": "static",
"buildCommand": "npm run build",
"outputDir": "dist"
}README.md:
# Astro Site
[](https://dashboard.pandastack.io/deploy?repo=yourusername/astro-site)
An Astro static site with fast cached builds.Push this to GitHub, click the deploy button, and the first build takes ~90 seconds. The second build takes ~30 seconds.
References
- [Astro Documentation](https://docs.astro.build/)
- [npm Cache Documentation](https://docs.npmjs.com/cli/v10/commands/npm-cache)
- [PandaStack Build System](https://docs.pandastack.io/projects/builds)