Getting persistent HTTP 429 directly from Railway's own edge
bco-ke
FREEOP

2 days ago

Getting persistent HTTP 429 directly from Railway's own edge — confirmed even on the raw .up.railway.app domain with no custom domain/CDN in front of it: server: railway-hikari, x-railway-edge: jnb1, x-hikari-trace: jnb1.x1wt. This is not coming from my application (my app's rate limiter only applies to /api/ and returns JSON; this is text/plain, 12 bytes). Persisting 25+ minutes across multiple retries, on both the custom domain and the raw Railway domain. Serverless is disabled. Project: f7ab6f63-aaa3-4887-9783-31046b5e744e, Service: 35c8b6e8-d11b-43ea-a5e0-9bc705288d77. Can you check why my service is being throttled/shielded at the edge (region jnb1)?

proof : n:https://j*production.up.railway.app~$ curl -sI

HTTP/2 429

content-type: text/plain; charset=utf-8

content-length: 12

x-hikari-trace: jnb1.x1wt

server: railway-hikari

x-railway-edge: jnb1

date: Sun, 05 Jul 2026 19:27:00 GMT

Given it's affecting the raw domain too, this is very likely either:

An account-level or project-level rate limit/abuse-shield triggered by today's high volume of rapid redeploys + repeated curl testing, or

A regional (jnb1 — Johannesburg edge) infrastructure issue on Railway's side

$10 Bounty

4 Replies

Railway
BOT

2 days ago

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

Status changed to Open Railway 1 day ago


hazzo01
PROTop 5% Contributor

2 days ago

Looking at Railway's docs, unless you we're somehow making >11,000 requests per second, it's likely not your testing that has caused this.

image.png

From my understanding, those response headers don't tell us "Railway Edge is blocking the requests". Instead, they are telling us, "this request went through a Railway Edge proxy".

A couple of things to check:

  1. Can you check the service logs, is there any that suggest traffic is actually getting to the container? If not, then the request is likely being blocked before it reaches the container.
  2. Can you ssh into the service, or another service in the project and carry out the same curl? This should bypass the edge proxy altogether
  3. What is the specific response body you're receiving? Does that give you any information about what is actually blocking the requests?
  4. Is there any headers relating to rate limiting? For example, Retry-After?

Attachments


bco-ke
FREEOP

17 hours ago

The Railway edge 429 issue is still active and is now hitting real usage

Every site.webmanifest, /api/auth/register, and /api/auth/login 429 in that log is the same unresolved Railway edge issue we reported to their support (railway-hikari), not a new bug. This confirms it's gotten worse — it's now throttling real user actions like login/register, not just our testing curls. Follow up on that support ticket urgently and reference this new evidence: real registration/login attempts are being blocked platform-wide, not just repeated test requests. error from my app side is 400 the rest is not mine ite.webmanifest:1

Failed to load resource: the server responded with a status of 429 ()

explore:1 Manifest fetch from https://jiranihub.com/site.webmanifest failed, code 429

api/estates/private:1

Failed to load resource: the server responded with a status of 401 ()

api/auth/me:1

Failed to load resource: the server responded with a status of 401 ()

api/auth/register:1

Failed to load resource: the server responded with a status of 400 ()

api/auth/register:1

Failed to load resource: the server responded with a status of 400 ()

api/auth/register:1

Failed to load resource: the server responded with a status of 400 ()

api/auth/me:1

Failed to load resource: the server responded with a status of 401 ()

api/estates/private:1

Failed to load resource: the server responded with a status of 401 ()

api/user/memberships:1

Failed to load resource: the server responded with a status of 401 ()

api/auth/register:1

Failed to load resource: the server responded with a status of 400 ()

api/auth/register:1

Failed to load resource: the server responded with a status of 400 ()

api/auth/register:1

Failed to load resource: the server responded with a status of 400 ()

api/auth/register:1

Failed to load resource: the server responded with a status of 400 ()

api/auth/register:1

Failed to load resource: the server responded with a status of 400 ()

api/auth/login:1

Failed to load resource: the server responded with a status of 401 ()

api/auth/login:1

Failed to load resource: the server responded with a status of 401 ()

api/auth/login:1

Failed to load resource: the server responded with a status of 429 ()

api/auth/register:1

Failed to load resource: the server responded with a status of 400 ()

api/auth/login:1

Failed to load resource: the server responded with a status of 429 ()

site.webmanifest:1

Failed to load resource: the server responded with a status of 429 ()

site.webmanifest:1

GET https://jiranihub.com/site.webmanifest 429 (Too Many Requests)

auth:1 Manifest fetch from https://jiranihub.com/site.webmanifest failed, code 429

auth.tsx:57

POST https://jiranihub.com/api/auth/register 429 (Too Many Requests)

(anonymous) @ auth.tsx:57

(anonymous) @ auth.tsx:124

auth.tsx:40

POST https://jiranihub.com/api/auth/login 429 (Too Many Requests)

(anonymous) @ auth.tsx:40

(anonymous) @ auth.tsx:123

Confirmation the ticket with Railway support has been updated with today's evidence of it affecting real login/register traffic


bco-ke
FREEOP

17 hours ago

on my side here is what i had done but it seems to bypass this logic

/* ── Rate limiting on auth endpoints ── */

const authLimiter = rateLimit({

  windowMs: 15 * 60 * 1000, // 15 minutes

  max: 200,                   // 200 attempts per window

  standardHeaders: true,

  legacyHeaders: false,

  keyGenerator: clientIpKey,

  message: { message: "Too many attempts, please try again later." },

  skip: () => Boolean(env.SKIP_RATE_LIMITS) || env.NODE_ENV !== "production", // allow toggle via env

});

const strictLimiter = rateLimit({

  windowMs: 60 * 60 * 1000, // 1 hour

  max: 50,                    // 50 registration attempts per hour

  standardHeaders: true,

  legacyHeaders: false,

  keyGenerator: clientIpKey,

  message: { message: "Too many registration attempts, please try again later." },

  skip: () => Boolean(env.SKIP_RATE_LIMITS) || env.NODE_ENV !== "production",

});

/* ── Camera test-connection probe: bounds outbound probing of public hosts ── */

const cameraTestLimiter = rateLimit({

windowMs: 5 * 60 * 1000,  // 5 minutes

max: 30,                   // 30 test probes per window

standardHeaders: true,

legacyHeaders: false,

keyGenerator: clientIpKey,

message: { message: "Too many connection tests, please wait a minute and try again." },

skip: () => Boolean(env.SKIP_RATE_LIMITS) || env.NODE_ENV !== "production",

});

/* ── Relay script download: rate-limits unauthenticated token look-ups to

    prevent brute-force enumeration of relay tokens ── */

const relayScriptLimiter = rateLimit({

windowMs: 15 * 60 * 1000, // 15 minutes

max: 15,                   // 15 script downloads per window per IP

standardHeaders: true,

legacyHeaders: false,

keyGenerator: clientIpKey,

message: "# Rate limit exceeded — too many token look-ups from this IP.\n",

skip: () => Boolean(env.SKIP_RATE_LIMITS) || env.NODE_ENV !== "production",

});


hazzo01
PROTop 5% Contributor

16 hours ago

The logs you outputted above, are they from Railway? If so, it looks like it may be the code that is doing the rate-limiting


Welcome!

Sign in to your Railway account to join the conversation.

Loading...