Medusa backend builds failing on Railway with npm registry 429 Too Many Requests
dluan
HOBBYOP

21 days ago

Our Medusa backend builds are consistently failing on Railway with 429 Too Many Requests errors from the npm registry (registry.npmjs.org). The same build succeeds locally, so this appears to be IP-based rate limiting affecting Railway's shared build egress.

Error details

During pnpm install, we get:

ERR_PNPM_FETCH_429 GET https://registry.npmjs.org/@medusajs%2Fjs-sdk: Too Many Requests - 429

This error happened while installing the dependencies of @medusajs/draft-order@2.17.2

The affected packages are Medusa core packages (@medusajs/js-sdk, @medusajs/types, @medusajs/modules-sdk), which are heavy dependencies of the Medusa backend.

What we have tried

Multiple redeploys from the latest source.

Adding retry and timeout settings to .npmrc:

fetch-retries=5

fetch-retry-mintimeout=20000

fetch-retry-maxtimeout=120000

fetch-timeout=300000

prefer-offline=true

Confirmed the lockfile (pnpm-lock.yaml) is committed and up to date.

Why we believe it is Railway-side rate limiting

The exact same build completes successfully on our local machine in ~51 seconds, downloading the same 1,427 packages. The only difference is the egress IP used by the Railway build environment versus our local network.

Request

Could you help us with one of the following?

Persistent package cache — Is it possible to enable a persistent pnpm store/cache across builds so we do not hit the npm registry on every deploy?

Build IP rotation / alternative region — Can we route the build through a different region or IP to avoid the currently rate-limited shared IP?

Registry mirror support — Do you support or recommend a private registry mirror (e.g., Verdaccio) to cache npm packages?

Immediate mitigation — Any other short-term workaround you can apply on your side.

Project/service details are available in our Railway dashboard. Let me know if you need deployment IDs or further logs.

Solved$10 Bounty

Pinned Solution

dluan
HOBBYOP

18 days ago

What we tried:

  • Increasing fetch-retries and fetch-timeout
  • Reducing network-concurrency
  • Caching the pnpm store mount in the Dockerfile

It all helps, but the initial build still needs to download the packages. And if the Railway IP is already rate-limited, the cache doesn't help.

The solution that worked

We switched to building the Docker image in GitHub Actions and publishing it to the GitHub Container Registry (GHCR). Railway then deployed using the ready-made image, without needing to run npm commands.

Workflow summary:

  • We created a multi-stage Dockerfile with a cache mount for the pnpm store.
  • We created a .github/workflows/docker-build.yml workflow that builds and pushes the image upon every merge to the master branch.
  • We configured Railway to deploy from:

ghcr.io/your-username/medusa-backend:master

9 Replies

Railway
BOT

21 days ago

This thread has been opened as a bounty so the community can help solve it.

Status changed to Open Railway 21 days ago


manuproject
HOBBY

21 days ago

The 429s happen because pnpm downloads a ton of packages in parallel and railways build ips are shared, so npm's rate limiter trips.

add network-concurrency=6 to your .npmrc and the burst goes away, install is a bit slower but no more 429s. keep your retry settings, they stack fine.

the bigger win is to stop pulling 1427 packages on every deploy. railway supports buildkit cache mounts in dockerfiles, which is basically the persistent pnpm store you can ask for something like :

RUN --mount=type=cache,id=pnpm-store,target=/pnpm/store pnpm install --frozen-lockfile

first good build fills the cache and after that you barely hit the registry at all. heads up that railway wants a specific id format for the cache mount (it includes your service id), the exact syntax is in their build docs.

once thats in place the shared ip thing mostly stops mattering, and you dont need verdaccio or a mirror


robbyuitbeijerse
FREE

21 days ago

We're in the same situation since yesterday, we're using bun but I guess that doesn't quite matter since both are just running HTTP requests to the npm registry. It happens on most of our builds, occasionally one passes but it's killing most of our builds at this point.

The cache suggestion is a good one, but that doesn't quite explain why this would suddenly happen, we've been running this service and have been spamming plenty of builds in short notice for more than a year.


tossivahva
FREE

20 days ago

  1. npm config set registry https://registry.npmmirror.com
  2. Wait for fix from Medusa devs
  3. change registry back to default: npm config set registry https://registry.npmjs.org/

Hope it will help


robbyuitbeijerse
FREE

18 days ago


tossivahva

1. **npm config set registry https://registry.npmmirror.com** 2. Wait for fix from Medusa devs 3. change registry back to default: **npm config set registry https://registry.npmjs.org/** Hope it will help

robbyuitbeijerse
FREE

18 days ago

if you consider advicing people to use an unknown third party registry to install dependencies for their (possibly) production software a good solution, you either have malicious intent or must be taking the short bus to school.


robbyuitbeijerse

if you consider advicing people to use an unknown third party registry to install dependencies for their (possibly) production software a good solution, you either have malicious intent or must be taking the short bus to school.

tossivahva
FREE

18 days ago

This is just China mirror from Alibaba as I know. No malicious intention from me. I will edit my post later how I solve this without third party registry mirror.


dluan
HOBBYOP

18 days ago

What we tried:

  • Increasing fetch-retries and fetch-timeout
  • Reducing network-concurrency
  • Caching the pnpm store mount in the Dockerfile

It all helps, but the initial build still needs to download the packages. And if the Railway IP is already rate-limited, the cache doesn't help.

The solution that worked

We switched to building the Docker image in GitHub Actions and publishing it to the GitHub Container Registry (GHCR). Railway then deployed using the ready-made image, without needing to run npm commands.

Workflow summary:

  • We created a multi-stage Dockerfile with a cache mount for the pnpm store.
  • We created a .github/workflows/docker-build.yml workflow that builds and pushes the image upon every merge to the master branch.
  • We configured Railway to deploy from:

ghcr.io/your-username/medusa-backend:master


Status changed to Solved dluan 18 days ago


manuproject

The 429s happen because pnpm downloads a ton of packages in parallel and railways build ips are shared, so npm's rate limiter trips. add network-concurrency=6 to your .npmrc and the burst goes away, install is a bit slower but no more 429s. keep your retry settings, they stack fine. the bigger win is to stop pulling 1427 packages on every deploy. railway supports buildkit cache mounts in dockerfiles, which is basically the persistent pnpm store you can ask for something like : RUN --mount=type=cache,id=pnpm-store,target=/pnpm/store pnpm install --frozen-lockfile first good build fills the cache and after that you barely hit the registry at all. heads up that railway wants a specific id format for the cache mount (it includes your service id), the exact syntax is in their build docs. once thats in place the shared ip thing mostly stops mattering, and you dont need verdaccio or a mirror

dluan
HOBBYOP

18 days ago

Thanks for the suggestions; I saw some improvements, but it wasn't enough to solve the problem. In the end, I had to work around the installation via the GitHub image.


Status changed to Awaiting Conductor Response Railway 18 days ago


robbyuitbeijerse

We're in the same situation since yesterday, we're using `bun` but I guess that doesn't quite matter since both are just running HTTP requests to the npm registry. It happens on most of our builds, occasionally one passes but it's killing most of our builds at this point. The cache suggestion is a good one, but that doesn't quite explain why this would suddenly happen, we've been running this service and have been spamming plenty of builds in short notice for more than a year.

dluan
HOBBYOP

18 days ago

Hi Robby, unfortunately, I had to work around the installation using GitHub; I’ve posted the steps I took to do that below. I hope this helps you too.


Status changed to Solved dev 18 days ago


Welcome!

Sign in to your Railway account to join the conversation.

Loading...