Guide
Updated 7 min read

Why Coolify Deploys Are Slow (And How to Make Them Vercel-Fast)

Coolify deploys feel slow because the defaults favour simplicity over speed. Three causes — undersized VPS, no build cache, wrong build strategy — and the fixes.

Why Coolify Deploys Are Slow (And How to Make Them Vercel-Fast)

"My Coolify deploy takes 4 minutes; on Vercel the same app deployed in 30 seconds." This complaint is real, and the fix isn't switching back to Vercel. It's recognising that Coolify gives you the levers to be fast — they just aren't on by default.

Slow deploys on Coolify almost always trace to one of three causes: under-sized VPS, no build cache, or the wrong build strategy for the app. Here's how to diagnose and fix each.

First: measure where the time goes

Before optimising, find out where the seconds actually go. Coolify's deploy log shows phase timings. Typical breakdown for a slow deploy:

Pulling source from git              5s
Building Docker image               180s
Pushing image to local registry     20s
Pulling image on target server      8s
Stopping old container              5s
Starting new container              12s
Health check                        20s
─────────────────────────────────
Total                              250s

The build phase dominates. That's the lever to pull.

Cause 1: Under-sized VPS

Building Docker images is CPU-and-IO bound. A $5 VPS with 1 vCPU and 1 GB RAM will absolutely take 4+ minutes for a Next.js or Rails build.

The cheap test: watch CPU and memory during a deploy.

# Run during a deploy
top -b -n 1 | head -20
free -m
df -h /var/lib/docker

If CPU is pinned at 100% for the full build, your CPU is the bottleneck. If swap is being touched, RAM is the bottleneck.

For most modern web apps, the deploy-friendly sweet spot is:

  • 2-4 vCPUs (parallel build steps actually parallelise)
  • 4-8 GB RAM (so npm install / pip install don't swap)
  • NVMe storage (HDD doubles or triples build time)

Going from a $5 VPS to a $20 VPS often cuts deploy time by 60% — and you save more in your time than you spend on the bigger box.

Cause 2: No build cache

By default, Coolify rebuilds Docker images from scratch every deploy. If your Dockerfile starts with RUN npm install, every deploy re-downloads every package.

Three fixes:

Fix A: Better Dockerfile layering

Make sure dependencies are installed before you copy your source code. The lockfile rarely changes, so the dependency layer caches well:

# Bad — rebuilds deps on every code change
COPY . .
RUN npm install
RUN npm run build

# Good — deps cached separately from code
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build

This single change can take a 3-minute build down to 30 seconds when only your source code changed.

Fix B: BuildKit cache mounts

If you're on a recent Docker (BuildKit enabled), use cache mounts for package managers:

# syntax=docker/dockerfile:1.4
FROM node:20-alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN --mount=type=cache,target=/root/.npm npm ci
COPY . .
RUN npm run build

The --mount=type=cache line keeps npm's download cache on the host between builds. First build is normal speed; subsequent builds skip re-downloads even if the lockfile changed.

Same pattern works for pip, apt, cargo, go modules, and pnpm.

Fix C: Coolify's "Build Pack" cache

In Coolify → Service → Build, set "Build Pack" appropriately. The "Nixpacks" pack is usually slower than a hand-written Dockerfile because it does broader detection. If you have a working Dockerfile, set Build Pack to "Dockerfile" and point at it.

Cause 3: Wrong build strategy

Some apps don't need to be rebuilt every deploy.

Static sites — pre-build and ship

If your app is a Next.js export, an Astro build, a Hugo site, etc., the artifact is static. Build once locally or in CI, push to a registry, and have Coolify pull the prebuilt image. Coolify becomes a deployer, not a builder.

# docker-compose for Coolify
services:
  app:
    image: ghcr.io/yourorg/yourapp:v1.2.3
    # No build: section. Coolify just pulls.

Deploy time drops from "build + push + deploy" to "pull + deploy" — usually 20-30 seconds total.

Multi-stage builds

If your final image is small but your build needs heavy tooling (Webpack, Maven, Gradle, etc.), use multi-stage:

FROM node:20 AS builder
WORKDIR /app
COPY . .
RUN npm ci && npm run build

FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/server.js"]

The runtime image is small, and Coolify pushes/pulls less data per deploy.

Skip rebuilds for CSS-only changes

If you're touching only CSS or templates and your tooling supports HMR or hot reload, you don't always need a full container rebuild. Set up a volume mount for the assets directory and docker compose restart the service instead of redeploying.

This is a development-mode optimisation; keep production deploys properly atomic.

The CI pipeline pattern

For teams shipping multiple times per day, the right pattern isn't "make Coolify build faster." It's:

  1. CI builds and pushes the image to a registry (GitHub Container Registry, Hetzner registry, etc.).
  2. Coolify pulls and deploys by image tag, no build phase at all.

Deploys become 20-30 second pull-and-restart events. CI can take its time and use bigger machines.

git push → GitHub Actions → docker build + push → webhook to Coolify → docker pull + restart

Coolify supports this via "Deploy from registry" mode plus a webhook trigger.

When the problem is the app, not Coolify

Some apps are slow to build no matter what. Java/Maven projects with hundreds of dependencies, Rails apps with asset pipeline compilation, large monorepos. For these, the answer isn't tuning Coolify — it's:

  • Caching the build artifact so deploys are pull-only.
  • Splitting the monorepo so only the changed service rebuilds.
  • Pre-warming dependencies in a base image you rebuild weekly.

The deploy speed feedback loop in your dev workflow matters. A 4-minute deploy makes you batch changes; a 30-second deploy makes you ship as you go. The latter is almost always better for product velocity.

Closing principle

Coolify deploy speed is a tuning problem, not a tool limitation. The default config favours simplicity over speed; the production-ready config is faster than most managed PaaS for everything except the very first deploy. Spend an hour on Dockerfile layering, build cache, and (if needed) a CI-to-registry pipeline, and you'll match Vercel-speed deploys on hardware you control.

coolify
deploy-speed
vps-sizing
build-cache

From across the StoicSoft network

Hand-curated reads on the same topic from sister sites in the StoicSoft family.

Keep reading

Guide
8 min

Coolify logs after Vercel — closing the route-level observability gap without OTel

Developers leaving Vercel for Coolify hit the same wall: where are the searchable route-level logs? Here's the smallest setup that gets you there without a full OpenTelemetry stack.

Best Of
7 min

Push, Bind a Domain, See Logs: Self-Hosted PaaS Without the YAML Sprawl

CapRover, Coolify, Dokploy, or raw VPS? Self-hosters want the Vercel workflow — push code, bind a domain or tunnel, see logs — without hand-maintaining YAML. How the options actually compare.

Alternatives
6 min

When Coolify API Limits Become a Team Provisioning Problem

Coolify is a strong self-hosted PaaS, but teams that need API-first project, team, and container provisioning should evaluate the workflow before standardizing on it.

Compare
9 min

Coolify vs Kubernetes: Which Is Production-Ready for Your Team?

Coolify and Kubernetes live at opposite ends of an operational complexity scale. The honest sizing decision (it isn't binary).

Guide
8 min

AI-assisted beginner deployments need a source-of-truth checklist before hosting breaks

Several fresh beginner threads point at the same gap between AI-generated instructions, website builders, GitHub, and real hosting. One user moved from Hostinger Horizon to Cursor/GitHub/Supabase to avoid higher builder pricing, but cannot tell why changes…

Guide
8 min

AI-assisted self-hosting breaks when logs, installers, and runtime state cross layers

Fresh support threads show a useful content angle: AI and docs can get users most of the way through self-hosting, but the hard failures happen across boundaries. One user spent two days trying to install uCore/CoreOS in a Proxmox VM with qcow2 and ignition…