CORS issues when connecting Next.js frontend hosted on Vercel to Express backend on AWS EC2

I’m having trouble with CORS errors when trying to connect my Next.js frontend (deployed on Vercel) to my Express.js backend running on AWS EC2. Even though I have configured CORS settings, the connection keeps failing.

Here’s my backend CORS configuration:

const permittedDomains = [
  "https://myapp.com",
  "https://www.myapp.com"
];

const corsConfig = {
  origin: (requestOrigin, done) => {
    if (!requestOrigin) {
      console.log("Request without origin - permitted");
      return done(null, true);
    }

    if (permittedDomains.includes(requestOrigin)) {
      console.log(`CORS approved for: ${requestOrigin}`);
      done(null, true);
    } else {
      console.log(`CORS rejected for: ${requestOrigin}`);
      done(new Error(`Access denied for origin: ${requestOrigin}`));
    }
  },
  credentials: true,
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],
  allowedHeaders: ['Content-Type', 'Authorization', 'X-API-Key']
};

server.use(cors(corsConfig));

And my frontend API setup using RTK Query:

export const apiSlice = createApi({
  baseQuery: customQuery,
  tagTypes: ["User", "Data"],
  endpoints: (builder) => ({
    fetchUser: builder.query({
      queryFn: async (params, api, options, baseQuery) => {
        try {
          const currentUser = await getUser();
          const authSession = await getSession();
          
          if (!authSession) {
            return {
              error: {
                status: 401,
                data: 'Authentication required'
              }
            };
          }

          const response = await baseQuery(`user/${authSession.userId}`);
          
          if (response.error) {
            return { error: response.error };
          }

          return { data: { currentUser, session: authSession, profile: response.data } };
        } catch (err) {
          return {
            error: {
              status: 'FETCH_ERROR',
              data: err.message || 'Failed to load user data'
            }
          };
        }
      }
    })
  })
});

I have set up a subdomain (api.myapp.com) for API calls and have Nginx configured on the EC2 instance. Should I add specific Nginx rules or proxy settings to resolve this CORS issue? What am I missing in my setup?

check if ur vercel domain matches exact with what’s in permittedDomains - vercel gives you yourapp.vercel.app by default, not your custom domain. also make sure api.myapp.com is actually pointing to your ec2 correctly.

Your CORS config is probably missing your actual Vercel domains. You’ve only got your custom domain in permittedDomains, but Vercel requests come from different URLs during dev or preview deployments. Add your Vercel-generated URLs to that array, including preview deployment patterns. Also, double-check that your frontend’s actually hitting api.myapp.com instead of going straight to your EC2 IP. I had the same issue - turns out my Nginx wasn’t passing CORS preflight OPTIONS requests through to Express. Make sure your Nginx config lets those through instead of blocking them at the proxy level.

wait, are u seeing any logs from that console.log in your cors config? i’d love to know what domain’s actually being sent in the origin header when vercel makes the request. might give us a clue about what’s going wrong.