aws-amplify / amplify-hosting

AWS Amplify Hosting provides a Git-based workflow for deploying and hosting fullstack serverless web applications.
https://aws.amazon.com/amplify/hosting/
Apache License 2.0
451 stars 113 forks source link

NextJs SSR Amplify, cold start takes up to 7 seconds #3855

Closed vincent38wargnier closed 7 months ago

vincent38wargnier commented 1 year ago

Before opening, please confirm:

JavaScript Framework

Next.js

Amplify APIs

Authentication, GraphQL API, Storage

Amplify Categories

auth, storage, function, api, hosting

Environment information

``` # Put output below this line System: OS: macOS 11.5.1 CPU: (8) arm64 Apple M1 Memory: 128.09 MB / 16.00 GB Shell: 5.8 - /bin/zsh Binaries: Node: 16.8.0 - /opt/homebrew/bin/node Yarn: 1.22.17 - /opt/homebrew/bin/yarn npm: 7.21.0 - /opt/homebrew/bin/npm Browsers: Chrome: 109.0.5414.119 Safari: 14.1.2 npmPackages: @ampproject/toolbox-optimizer: undefined () @aws-amplify/ui-react: ^4.3.2 => 4.3.2 @aws-amplify/ui-react-internal: undefined () @aws-sdk/client-s3: ^3.224.0 => 3.226.0 (3.6.1) @babel/core: undefined () @babel/runtime: 7.15.4 @edge-runtime/primitives: 2.0.0 @hapi/accept: undefined () @napi-rs/triples: undefined () @next/react-dev-overlay: undefined () @react-icons/all-files: ^4.1.0 => 4.1.0 @segment/ajv-human-errors: undefined () @vercel/nft: undefined () acorn: undefined () amphtml-validator: undefined () anser: undefined () arg: undefined () assert: undefined () async-retry: undefined () async-sema: undefined () autoprefixer: ^10.4.13 => 10.4.13 aws-amplify: ^5.0.8 => 5.0.8 babel-packages: undefined () blueimp-load-image: ^5.16.0 => 5.16.0 browserify-zlib: undefined () browserslist: undefined () buffer: undefined () bytes: undefined () chalk: undefined () ci-info: undefined () cli-select: undefined () comment-json: undefined () compress.js: ^1.2.2 => 1.2.2 compression: undefined () conf: undefined () constants-browserify: undefined () content-disposition: undefined () content-type: undefined () cookie: undefined () cross-spawn: undefined () crypto-browserify: undefined () css.escape: undefined () cssnano-simple: undefined () data-uri-to-buffer: undefined () debug: undefined () devalue: undefined () domain-browser: undefined () edge-runtime: undefined () events: undefined () find-cache-dir: undefined () find-up: undefined () fresh: undefined () get-orientation: undefined () glob: undefined () gzip-size: undefined () http-proxy: undefined () https-browserify: undefined () icss-utils: undefined () ignore-loader: undefined () image-size: undefined () is-animated: undefined () is-docker: undefined () is-wsl: undefined () jest-worker: undefined () json5: undefined () jsonwebtoken: undefined () leaflet: ^1.9.3 => 1.9.3 leaflet-defaulticon-compatibility: ^0.1.1 => 0.1.1 loader-utils: undefined () lodash.curry: undefined () lru-cache: undefined () micromatch: undefined () mini-css-extract-plugin: undefined () nanoid: undefined () native-url: undefined () neo-async: undefined () next: 13.0.4 => 13.0.4 node-fetch: undefined () node-html-parser: undefined () ora: undefined () os-browserify: undefined () p-limit: undefined () path-browserify: undefined () piexifjs: ^1.0.6 => 1.0.6 platform: undefined () postcss: ^8.4.19 => 8.4.19 (8.4.14) postcss-flexbugs-fixes: undefined () postcss-modules-extract-imports: undefined () postcss-modules-local-by-default: undefined () postcss-modules-scope: undefined () postcss-modules-values: undefined () postcss-preset-env: undefined () postcss-safe-parser: undefined () postcss-scss: undefined () postcss-value-parser: undefined () process: undefined () punycode: undefined () querystring-es3: undefined () raw-body: undefined () react: 18.2.0 => 18.2.0 (18.3.0-next-4bd245e9e-20221104) react-beautiful-dnd: ^13.1.1 => 13.1.1 react-dom: 18.2.0 => 18.2.0 (18.3.0-next-4bd245e9e-20221104) react-icons: ^4.7.1 => 4.7.1 react-is: 18.2.0 react-leaflet: ^4.2.0 => 4.2.0 react-refresh: 0.12.0 react-server-dom-webpack: undefined () react-slideshow-image: ^4.1.0 => 4.1.1 react-tooltip: ^4.5.1 => 4.5.1 regenerator-runtime: 0.13.4 sass-loader: undefined () scheduler: undefined () schema-utils: undefined () semver: undefined () send: undefined () setimmediate: undefined () shell-quote: undefined () source-map: undefined () stacktrace-parser: undefined () stream-browserify: undefined () stream-http: undefined () string-hash: undefined () string_decoder: undefined () strip-ansi: undefined () tailwind-merge: ^1.8.0 => 1.8.0 tailwindcss: ^3.2.4 => 3.2.4 tar: undefined () terser: undefined () text-table: undefined () timers-browserify: undefined () tty-browserify: undefined () ua-parser-js: undefined () undici: undefined () unistore: undefined () util: undefined () vm-browserify: undefined () watchpack: undefined () web-vitals: undefined () webpack: undefined () webpack-sources: undefined () ws: undefined () npmGlobalPackages: @aws-amplify/cli: 10.5.2 @ionic/cli: 6.17.1 npm: 7.21.0 prebuild-install: 7.1.1 yarn: 1.22.17 ```

Describe the bug

Hi, I have created an AWS Amplify Web app with NextJs SSR. Everything works fine except one huge issue : cold start takes up to 7 seconds to have server response.

I realized that if I remove all my amplify backend, the cold start drops down to less than a second. So I guess the problem comes from the AWS Amplify libraries.

I deployed a version of my website that doesn't call any getServerSideProps, but the latency stays around 7 seconds.

image

This is my amplify backend configuration :

{
  "auth": {
    "userPoolGroups": {
      "service": "Cognito-UserPool-Groups",
      "providerPlugin": "awscloudformation",
      "dependsOn": [
        {
          "category": "auth",
          "resourceName": "ressourceNamef1xxxxxxxxx",
          "attributes": [
            "UserPoolId",
            "AppClientIDWeb",
            "AppClientID",
            "IdentityPoolId"
          ]
        }
      ]
    },
    "ressourceNamef1xxxxxxxxx": {
      "service": "Cognito",
      "providerPlugin": "awscloudformation",
      "dependsOn": [],
      "customAuth": false,
      "frontendAuthConfig": {
        "socialProviders": [],
        "usernameAttributes": [
          "EMAIL"
        ],
        "signupAttributes": [
          "EMAIL"
        ],
        "passwordProtectionSettings": {
          "passwordPolicyMinLength": 8,
          "passwordPolicyCharacters": []
        },
        "mfaConfiguration": "OFF",
        "mfaTypes": [
          "SMS"
        ],
        "verificationMechanisms": [
          "EMAIL"
        ]
      }
    }
  },
  "api": {
    "ressourceName": {
      "service": "AppSync",
      "providerPlugin": "awscloudformation",
      "dependsOn": [
        {
          "category": "auth",
          "resourceName": "ressourceNamef1xxxxxxxxx",
          "attributes": [
            "UserPoolId"
          ]
        }
      ],
      "output": {
        "authConfig": {
          "defaultAuthentication": {
            "authenticationType": "AMAZON_COGNITO_USER_POOLS",
            "userPoolConfig": {
              "userPoolId": "authressourceNamef1xxxxxxxxx"
            }
          },
          "additionalAuthenticationProviders": [
            {
              "authenticationType": "API_KEY",
              "apiKeyConfig": {
                "apiKeyExpirationDays": 365,
                "apiKeyExpirationDate": "2023-12-10T15:07:46.361Z",
                "description": ""
              }
            },
            {
              "authenticationType": "AWS_IAM"
            }
          ]
        }
      }
    }
  },
  "storage": {
    "s338e9026f": {
      "service": "S3",
      "providerPlugin": "awscloudformation",
      "dependsOn": [
        {
          "category": "auth",
          "resourceName": "ressourceNamef1xxxxxxxxx",
          "attributes": [
            "UserPoolId"
          ]
        },
        {
          "category": "auth",
          "resourceName": "userPoolGroups",
          "attributes": [
            "adminGroupRole"
          ]
        },
        {
          "category": "auth",
          "resourceName": "userPoolGroups",
          "attributes": [
            "superAdminGroupRole"
          ]
        }
      ]
    }
  },
  "function": {
    "ressourceNameSendEmails": {
      "build": true,
      "providerPlugin": "awscloudformation",
      "service": "Lambda",
      "dependsOn": [
        {
          "category": "api",
          "resourceName": "ressourceName",
          "attributes": [
            "GraphQLAPIIdOutput",
            "GraphQLAPIEndpointOutput",
            "GraphQLAPIKeyOutput"
          ]
        }
      ]
    },
    "getgooglereviews": {
      "build": true,
      "providerPlugin": "awscloudformation",
      "service": "Lambda",
      "dependsOn": [
        {
          "category": "auth",
          "resourceName": "ressourceNamef1xxxxxxxxx",
          "attributes": [
            "UserPoolId"
          ]
        },
        {
          "category": "api",
          "resourceName": "ressourceName",
          "attributes": [
            "GraphQLAPIIdOutput",
            "GraphQLAPIEndpointOutput",
            "GraphQLAPIKeyOutput"
          ]
        }
      ]
    }
  }
}

Here is the way my NexJs App is initialized with amplify :

import '../styles/globals.css'
import { ContextProvider } from '../src/components/context/Context';
import Layout from '../src/components/Layout';
import '@aws-amplify/ui-react/styles.css';
import { Amplify } from 'aws-amplify';
import awsExports from '../src/aws-exports';

function MyApp({ Component, pageProps }) {
  Amplify.configure(awsExports);
//Amplify.configure({ ...awsExports, ssr: true }); //==> This doesn't change latency. issue
  return (
    <ContextProvider>
      <Layout>
        <Component {...pageProps} />
      </Layout>
    </ContextProvider>
  )
}

export default MyApp

I read on several forums that Amplify is not able to provide law latency cold start, so I better move to Vercel or Netlify (which I tried and works super well) for example. Can you please confirm the opposite? Sources : https://www.reddit.com/r/nextjs/comments/uamqbl/beware_of_nextjs_on_aws_amplify/

I also found some other solutions like keeping the lambda warm with a cron job. Is that a good idea? https://www.reddit.com/r/nextjs/comments/ml4i2t/ssr_pages_cold_start_improve_performance/

Thank you.

Expected behavior

I would like to have cold start no longer than 1 second, as it is on most of other cloud providers.

Reproduction steps

amplify init amplify add auth amplify add api amplify add storage amplify add function amplify add hosting amplify push

Code Snippet

// Put your code below this line.

Log output

``` // Put your logs below this line ```

aws-exports.js

/ eslint-disable / // WARNING: DO NOT EDIT. This file is automatically generated by AWS Amplify. It will be overwritten.

const awsmobile = { "aws_project_region": "eu-west-2", "aws_cognito_identity_pool_id": "eu-west-2:xxxxxxxxxxxxxxx", "aws_cognito_region": "eu-west-2", "aws_user_pools_id": "eu-west-2_xxxxxxxxxxxxxxx", "aws_user_pools_web_client_id": "xxxxxxxxxxxxxxx", "oauth": {}, "aws_cognito_username_attributes": [ "EMAIL" ], "aws_cognito_social_providers": [], "aws_cognito_signup_attributes": [ "EMAIL" ], "aws_cognito_mfa_configuration": "OFF", "aws_cognito_mfa_types": [ "SMS" ], "aws_cognito_password_protection_settings": { "passwordPolicyMinLength": 8, "passwordPolicyCharacters": [] }, "aws_cognito_verification_mechanisms": [ "EMAIL" ], "aws_appsync_graphqlEndpoint": "https://xxxxxxxxxxxxxxx.amazonaws.com/graphql", "aws_appsync_region": "eu-west-2", "aws_appsync_authenticationType": "AMAZON_COGNITO_USER_POOLS", "aws_appsync_apiKey": "xxxxxxxxxxxxxxx", "aws_user_files_s3_bucket": "xxxxxxxxxxxxxxx", "aws_user_files_s3_bucket_region": "eu-west-2" };

export default awsmobile;

Manual configuration

No response

Additional configuration

No response

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

mauerbac commented 7 months ago

Hey everyone -- we've examined app performance across the board and don't see holistic issues that would contribute to slow starts/time to first byte. There are many factors at play and it is more effective to examine each app on a case by case basis to identify potential issues. If you are still experiencing this issue, please open a AWS Support case or ask in our Community Discord server