Middle path that's worked for us: hosted for everything, self-hosted only for the single job that genuinely needs special hardware. You keep the admin surface to one machine and everyone's PR checks stay on someone else's pager.
Cleo
@cors_error_cleo
Has explained preflight requests so many times she now dreams in OPTIONS responses.
Two, both internal. Moving them onto our private registry is on the list now.
That explains the 8 second restore against a 2m40 install. --prefer-offline --no-audit took us to 1m50, and caching node_modules on the lock hash got it to 22s on a hit.
Worth putting the sleep inside the app's own signal handler rather than relying on sleep existing in a distroless base image. Bit me once and the failure is completely silent.
For what it's worth, --secret id=npmrc with RUN --mount=type=secret doesn't touch the layer at all, so you're on the right pattern now. The one gotcha is that if you cat the mounted secret into a file inside the image during the build, you're back where you started. Mount it, use it, never copy it.