CORS Preflight Failure After Upgrading to Hobby Plan
dipeshoffical
HOBBYOP

6 months ago

I recently upgraded my project from the Free plan to the Hobby plan. Since the upgrade, my Express.js backend hosted on Railway is experiencing CORS preflight failures. Preflight OPTIONS requests to endpoints such as /api/auth/login are failing with the following error in the browser:

Access to XMLHttpRequest at 'https://consultancypro-production.up.railway.app/api/auth/login' from origin 'https://consultancy-frontend-pro.vercel.app' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Project Details:

  • Frontend:https://consultancy-frontend-pro.vercel.app

  • Backend:https://consultancypro-production.up.railway.app

  • Backend Stack: Node.js + Express.js + Sequelize + MySQL

  • CORS Setup: Using cors middleware in Express with credentials: true and a whitelist of allowed origins. Middleware is placed before routes and handles preflight OPTIONS requests.

  • Status: This setup was working correctly on the Free plan. After upgrading to the Hobby plan, all cross-origin POST requests fail with the error above.

I have confirmed that:

  • My frontend origin matches the whitelist.

  • The backend is reachable and responding to direct requests.

  • Preflight OPTIONS requests are reaching the server but are missing the Access-Control-Allow-Origin header.

Could you please advise if there are any changes in reverse proxy, preflight handling, or other plan-related differences on the Hobby plan that could be causing this issue? Guidance on resolving this would be highly appreciated.

$10 Bounty

6 Replies

brody
EMPLOYEE

6 months ago

This thread has been marked as public for community involvement, as it does not contain any sensitive or personal information. Any further activity in this thread will be visible to everyone.

Status changed to Open brody 6 months ago


grillekkj
FREE

6 months ago

Hey! Can you try adding something like this to your server.js before your other routes and share the output?

- You can adjust the configuration (add, remove, or change values) based on your needs.
You can find the docs with all options here => https://expressjs.com/en/resources/middleware/cors.html?utm_source=chatgpt.com#configuration-options

const corsOptions = {

origin: 'https://consultancy-frontend-pro.vercel.app',

credentials: true,

methods: ['GET','HEAD','PUT','PATCH','POST','DELETE','OPTIONS'],

allowedHeaders: ['Content-Type', 'Authorization'],

maxAge: 86400

};

app.use(cors(corsOptions));

app.options('*', cors(corsOptions));


dipeshoffical
HOBBYOP

6 months ago

okay let me give it a try


grillekkj
FREE

6 months ago

Did it work?


dipeshoffical
HOBBYOP

6 months ago

no it didn't , but it will work if i do a entirely new deployment.


dipeshoffical
HOBBYOP

6 months ago

okay any public review

, it only has to do with the preflight.


hamedshams
FREE

6 months ago

Short answer

There’s no plan-level proxy change on Hobby that alters CORS. If a fresh deployment works but the current one fails, it’s almost always (a) middleware order or (b) stale deploy not picking up config.

---

.

Do this (in order):

1. Handle OPTIONS before everything else (incl. auth).

js

import cors from 'cors';

const ORIGINS = ['https://consultancy-frontend-pro.vercel.app']; // add others if needed
const corsOptions = {
  origin: ORIGINS,
  credentials: true,
  methods: ['GET','HEAD','PUT','PATCH','POST','DELETE','OPTIONS'],
  // Tip: omit allowedHeaders to let the library reflect Access-Control-Request-Headers
  maxAge: 86400,
};

app.use((req,res,next)=>{ res.set('Vary','Origin'); next(); });
app.options('*', cors(corsOptions));   // preflight first
app.use(cors(corsOptions));            // then regular routes
// ⬇ put auth/routers AFTER cors

(Express cors docs show origin, credentials, etc. and using app.options('*', cors(...)) for preflight.)

---

2. Remove allowedHeaders unless you must lock it down.

Hard-coding headers can fail preflight if the browser asks for extra ones (the middleware will reflect them automatically when not specified).

---

3. Verify with cURL (should return 204 + CORS headers):

bash

curl -i -X OPTIONS 'https://consultancypro-production.up.railway.app/api/auth/login' \
  -H 'Origin: https://consultancy-frontend-pro.vercel.app' \
  -H 'Access-Control-Request-Method: POST' \
  -H 'Access-Control-Request-Headers: Content-Type, Authorization'

If you don’t see Access-Control-Allow-Origin echoed to your origin and Access-Control-Allow-Credentials: true, your CORS middleware still isn’t running. See MDN note on the missing header error.

---

4. Redeploy to apply changes.

Env/setting changes in Railway are staged until you click Deploy; only then does the running service pick them up. (A “new deployment” working aligns with this.)

---

.

Notes

  • Hobby vs Free: pricing/limits differ, but CORS behavior is app-side; there’s no plan toggle that adds/removes CORS headers.

  • If you use credentials: true, don’t use origin: '*'; either list exact origins or set a function/`true` to reflect the request origin.

  • If an auth middleware rejects OPTIONS, exempt it: if (req.method === 'OPTIONS') return next();.

That sequence fixes nearly all “preflight started failing after an upgrade” reports; your successful fresh deploy is the tell that ordering/staging was the culprit.


Loading...