Skip to content

Trim ~95MB of Prisma Studio from the runtime image - #9

Merged
theNEXlevel merged 1 commit into
mainfrom
perf/trim-prisma-cli
Aug 8, 2026
Merged

Trim ~95MB of Prisma Studio from the runtime image#9
theNEXlevel merged 1 commit into
mainfrom
perf/trim-prisma-cli

Conversation

@theNEXlevel

Copy link
Copy Markdown
Contributor

Why

Measured from template's last deploy (202s total):

Phase Elapsed
clone + prepare 0 → 25s
image pull + extract 29s → 151s
container start → healthy 151s → 185s

~120s — 60% of the deploy — is pulling and extracting the image, and layer decompression is what pegged the server CPU. Coolify stops the old container at +18s but the new image isn't ready until +151s, so this is also the no available server window.

ghcr.io/c4g/template was the largest of the three images at 716MB, and 252MB of it was the Prisma CLI tree added when migrations moved into the app image — mostly @prisma/studio-core and its UI stack (effect, @electric-sql, react-dom, elkjs), none of which migrate deploy loads.

What

Deleting the package does not work — the CLI eagerly requires several @prisma/studio-core subpaths:

Error: Cannot find module '@prisma/studio-core/data/bff'
Error: Cannot find module '@prisma/studio-core/data/mysql2'   # after stubbing the first

So the migrator stage now installs it with an npm override pointing at a stub whose exports map wildcards every subpath, and --install-links so the stub is copied rather than symlinked (a symlink would dangle once node_modules is COPYed into the runner stage).

Image: 685MB → 591MB locally (the migrator tree itself goes 252MB → 156MB).

Verified

Built and ran the full production stack against the trimmed image:

  • All 4 migrations applied, migration container exited 0
  • App reached healthy
  • GET /api/notifications/subscribe{"publicKey":"trimkey"} — runtime env still read correctly

The publish workflow's smoke test exercises this same path against the published image, so if a future Prisma upgrade changes which subpaths the CLI requires, it fails in CI before anything deploys rather than breaking a deployment.

Related change (not in this PR)

Template's Coolify docker_compose_custom_build_command was changed from ... build to ... pull. That phase runs at +12.9s, before "Removing old containers" at +18.4s, so the image is pulled while the old container is still serving. Together these should cut the outage from ~2.5 minutes to seconds. Merging this PR triggers a deploy that will exercise it.

🤖 Generated with Claude Code

The migrator stage pulled in @prisma/studio-core and its UI stack (effect,
@electric-sql, react-dom, elkjs) — about 95MB that `migrate deploy` never
loads. Deleting it does not work: the CLI eagerly requires several
@prisma/studio-core subpaths and dies with 'Cannot find module'. An npm
override pointing at a stub with a wildcard exports map satisfies every
subpath, and --install-links copies the stub into node_modules so it survives
the COPY into the runner stage.

Image drops from 685MB to 591MB. Pull and extract was ~120s of template's
202s deploy, and the old container is stopped before it starts, so this
shortens the outage window on every deploy.

Verified against the full production stack: all 4 migrations applied, the
container exited 0, the app came up healthy and served the VAPID key.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@theNEXlevel
theNEXlevel merged commit 2cdf191 into main Aug 8, 2026
1 check passed
@theNEXlevel
theNEXlevel deleted the perf/trim-prisma-cli branch August 8, 2026 06:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant