CORS Almost Broke Me But Preflight Saved the Day
Haripriya Veluchamy

Haripriya Veluchamy @techwithhari

About: software engineer with a deep passion for DevOps and cloud technologies.

Location:
Tamilnadu, India
Joined:
Aug 11, 2024

CORS Almost Broke Me But Preflight Saved the Day

Publish Date: Oct 14
11 2

When I first built my frontend-backend setup, I thought everything would be smooth. Frontend hosted on S3, backend running Apollo GraphQL, and API Gateway sitting in the middle to handle requests safely. Sounds simple, right?

Well… browsers had other plans.

Every request I made from the frontend to the backend kept failing.
The console kept screaming:

Access to fetch at 'https://api.mybackend.com/graphql' 
from origin 'https://myfrontend.com' has been blocked by CORS policy
Enter fullscreen mode Exit fullscreen mode

I triple-checked my backend, triple-checked API Gateway. Everything was “working”… but the browser refused to cooperate.


What I finally understood

CORS isn’t a bug. It’s the browser saying:

“Hold on, I don’t trust this request from another domain unless the server says it’s okay.”

And the browser always starts with a preflight request an OPTIONS request that asks the server:

  • Am I allowed to send requests from this origin?
  • Which HTTP methods can I use (GET, POST, etc.)?
  • Which headers can I include?

If the server or the API Gateway doesn’t answer correctly, the browser blocks the actual request.
That’s why Postman worked but the frontend didn’t.


How I finally fixed it

The fix came in two parts:

1️⃣ Handle preflight at the API Gateway
I made sure that the OPTIONS request was correctly handled and that the gateway responded with the allowed origins, methods, and headers. Once this handshake worked, the browser let the real requests go through.

2️⃣ Backend trusted the frontend
On the Apollo server, I set it up to allow requests from the frontend domain dynamically. Passing the frontend URL as an environment variable made deployments safe — no hardcoding, no accidental errors.


Lessons learned

  • Preflight is everything. If it fails, nothing else works.
  • API Gateway must respond correctly to OPTIONS requests.
  • Backend still needs to explicitly allow the frontend domain.
  • Always manage allowed origins through environment variables.
  • Debugging tip: check the preflight request in the Network tab, not your GraphQL query itself.

After that, my frontend finally talked to my backend without errors — no more random CORS headaches or temporary hacks.

Sometimes the smallest headers cause the biggest headaches 🥲.


Comments 2 total

  • B.V. CHANDRAHAAS
    B.V. CHANDRAHAASOct 15, 2025

    if seperate services are exposed as subdomains such as service1.domain.com and service2.domain.com, the host differs which will trigger CORS. so, if we can expose the service while maintaining domain as the gateway, Browser won't consider that the request is coming from different domain. (domain.com/service1, domain.com/service2)

    • Haripriya Veluchamy
      Haripriya VeluchamyOct 15, 2025

      thanks for your insight i will try this but some times we cant directly use the domain name like you mentioned so based on the use case will use

Add comment