jetbridge / cdk-nextjs

Deploy a NextJS application using AWS CDK
https://constructs.dev/packages/cdk-nextjs-standalone
Apache License 2.0
273 stars 45 forks source link

Multi-tenant deploy error (CloudFront HTTP 409) #201

Closed yashvesikar closed 8 months ago

yashvesikar commented 8 months ago

I recently upgraded from v4.0.0-beta.1 to v4.0.0-beta.25 and started facing a issue when trying to deploy multiple apps in a single AWS account.

The logs in the cdk deploy output point to CloudFront being the culprit but it is not immediately clear what the issue is. The outputted error is:

2:01:02 PM | CREATE_FAILED        | AWS::CloudFront::Function                       | NextAppDistributionCloudFrontFnAC9E1010
Resource handler returned message: "Invalid request provided: AWS::CloudFront::Function: null (Service: CloudFront, Status Code: 409, Request ID: 0578ff41-24cd-4c16-8b49-0688aacff26d)" (RequestToken: 08f38d0f-c97a-009a-b703-978403819344, HandlerErrorCode:
InvalidRequest)

I have tried the following on version 25:

Downgrading to v4.0.0-beta.1 allowed us to deploy multiple apps in the same account again.

Any direction on what might be causing these deployment failures would be much appreciated.

bestickley commented 8 months ago

@yashvesikar, thanks for reporting this issue. Does looking at the diff of generated CloudFormation for AWS::CloudFront::Function between beta-1 and beta-25 reveal anything? It's not clear to me what the root issue is. You're correct that cloudFrontFunctionProps override is not properly being passed to constructor. I will fix that.

nshki commented 8 months ago

Hi @bestickley. I'm currently working with @yashvesikar on the same team and we have been trying to debug this together. Thanks for such a quick response.

To answer your question, beta.1 doesn't have AWS::CloudFront::Function in the generated CloudFormation stack while beta.25 does. The output from beta.25 looks like this:

  NextAppDistributionCloudFrontFnAC9E1010:
    Type: AWS::CloudFront::Function
    Properties:
      AutoPublish: true
      FunctionCode: "

        \      function handler(event) {

        \        var request = event.request;

        \        request.headers[\"x-forwarded-host\"] = request.headers.host;

        \        return request;

        \      }

        \      "
      FunctionConfig:
        Comment: us-east-1StackNextApDistributionCloudFrontFn7A838F99
        Runtime: cloudfront-js-1.0
      Name: us-east-1StackNextApDistributionCloudFrontFn7A838F99
    Metadata:
      aws:cdk:path: Stack/NextApp/Distribution/CloudFrontFn/Resource

We'd ideally like to stay on beta.25 if possible since downgrading the construct and redeploying on production will require some downtime due to our use of some custom domain config. Any advice would be appreciated!

bestickley commented 8 months ago

@nshki, I see. Are you instantiating NextjsDistribution multiple times and the same CloudFront Function name is being used for multiple functions? Is that the key issue?

nshki commented 8 months ago

We're not explicitly instantiating NextjsDistribution in our CDK code, but we do have some cache policy prop overrides in place. (Not sure if that affects the number of times NextjsDistribution is instantiated under the hood.)

This is a snippet of how we instantiate Nextjs:

  const nextApp = new Nextjs(scope, "NextApp", {
    nextjsPath: "../web/",
    domainProps: {
      domainName: appDomain,
      certificate,
      hostedZone: hostedZone.hostedZone,
    },
    overrides: {
      nextjsDistribution: {
        imageCachePolicyProps: {
          cachePolicyName: `${stackName}NextAppDistributionImageCachePolicy`,
        },
        serverCachePolicyProps: {
          cachePolicyName: `${stackName}NextAppDistributionServerCachePolicy`,
        },
      },
      nextjsServer: {
        functionProps: {
          timeout: Duration.seconds(300),
          environment: environmentVariables,
        },
      },
    },
    environment: environmentVariables,
  });
bestickley commented 8 months ago

Each app you're deploying into the same AWS account has CloudFront functions with different names, correct?

Not sure if that affects the number of times NextjsDistribution is instantiated under the hood

No.

nshki commented 8 months ago

Each app you're deploying into the same AWS account has CloudFront functions with different names, correct?

Ah you know what, we weren't. We were using a string literal of "NextApp" when instantiating Nextjs which would conflict if we have multiple deploys in the same AWS account. I just tested making this string unique per deploy and it's now working.

Thank you for your quick responses, @bestickley! Funny how rubber ducking always works like this in our careers. 😂

This issue is good to close.