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
450 stars 113 forks source link

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

Closed vincent38wargnier closed 6 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

nadetastic commented 1 year ago

Hi @vincent38wargnier thanks for opening this issue. This seems a bit related to aws-amplify/amplify-js#8918 but I have a few questions:

vincent38wargnier commented 1 year ago

Hi @vincent38wargnier thanks for opening this issue. This seems a bit related to aws-amplify/amplify-js#8918 but I have a few questions:

  • Have you been able to deploy and get the same results with ssr: false on Amplify.configure()?
  • Are you experiencing the same latency on localhost?

Hi @nadetastic, you're right it's related to this issue, but mine being much longer I was wondering if it was the exact same source of problem.

I don't have the problem in localhost, it's only in prod, during cold start. So if no user have been on the website for few minutes, the next one that queries it will have a 7 sec latency more or less. Once the cold start has been done, refreshing the page just takes max 1 sec, even if it's on another browser or other machine.

I saw that a solution is to keep it warm, with this plugin for example https://github.com/juanjoDiaz/serverless-plugin-warmup but I guess it's going to increase the general costs. I was also trying to make a lambda that pings the website every 2 minutes to keep the server busy.

I think the time that takes the cold start might be related to some serverless functions called by amplify, because when I remove amplify from the project and keep all the rest of the front end, the cold start time drops down to 1 sec. I tried also to remove the SSR functions, to only have front-end, but while amplify is still configured in the project, the cold starts keeps taking around 7 sec.

So I guess there is some time consuming in the cold start, might be the auth verification or some other amplify stuff. That's a good question I would say :/

Running this lambda triggered every 5 min solves the pb, but I don't know how much it's gonna cost...

const url = "https://yoururl.com/"
exports.handler = async (event) => {
    var axios = require('axios');

    let response = await axios({
        method: 'get',
        url,
        headers: {}
    })
    return response.data.result
};

Edit : this solution is not working, weirdly even if the lambda keeps warm a docker somewhere, when I load the site on my browser, 25% of the time the cold start is still existing. Here is the lambda duration, showing that the time of loading of the site is super slow because it's warm somewhere in the cloud. I guess this is due to geography. The lambda triggered is in eu-west-3 and I'm also in this region physically. Weird though

image

So for now I didn't find any solution to make my site sellable in the pro wolrd.

Edit 2: Yes the same cold start is visible in localhost when we work directly with the online environment :

image
jwang-lilly commented 1 year ago

I'd like to confirm I experienced the exact same issue as @vincent38wargnier. 7 seconds for the app to respond and another 3-5 seconds to load a page using client-side data fetch of about forty rows of data from dynamodb. Afterward, I went to another computer to bring up the app, it took less than 1 sec.
AWS amplify team, this issue, if unresolved, makes the app unsuitable for real-world use. I'd greatly appreciate you give it a high priority.

vincent38wargnier commented 1 year ago

Hi guys, To find out what's the problem, I decided to restart a project from zero and following the documentation here : https://docs.amplify.aws/start/getting-started/installation/q/integration/next/

My approach here is to publish the app at any step and compare the evolution of the cold start time.

Here is the result of the cold start :

image

cold start is already 1.78sec with nothing happening in the backend yet, so not very hopefull for the next steps.

So more or less we add a page index that ask the user to login through Cognito and then the user can access to the list of posts. here is the code :

// pages/index.js
import { Authenticator } from '@aws-amplify/ui-react';
import { Amplify, API, Auth, withSSRContext } from 'aws-amplify';
import Head from 'next/head';
import awsExports from '../aws-exports';
import { createPost } from '../graphql/mutations';
import { listPosts } from '../graphql/queries';
import styles from '../styles/Home.module.css';

Amplify.configure({ ...awsExports, ssr: true });

export async function getServerSideProps({ req }) {
  const SSR = withSSRContext({ req });

  try {
    const response = await SSR.API.graphql({ query: listPosts, authMode: 'API_KEY' });
    return {
      props: {
        posts: response.data.listPosts.items,
      },
    };
  } catch (err) {
    console.log(err);
    return {
      props: {},
    };
  }
}

async function handleCreatePost(event) {
  event.preventDefault();

  const form = new FormData(event.target);

  try {
    const { data } = await API.graphql({
      authMode: 'AMAZON_COGNITO_USER_POOLS',
      query: createPost,
      variables: {
        input: {
          title: form.get('title'),
          content: form.get('content')
        }
      }
    });

    window.location.href = `/posts/${data.createPost.id}`;
  } catch ({ errors }) {
    console.error(...errors);
    throw new Error(errors[0].message);
  }
}

export default function Home({ posts = [] }) {
  return (
    <div className={styles.container}>
      <Head>
        <title>Amplify + Next.js</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main className={styles.main}>
        <h1 className={styles.title}>Amplify + Next.js</h1>

        <p className={styles.description}>
          <code className={styles.code}>{posts.length}</code>
          posts
        </p>

        <div className={styles.grid}>
          {posts.map((post) => (
            <a className={styles.card} href={`/posts/${post.id}`} key={post.id}>
              <h3>{post.title}</h3>
              <p>{post.content}</p>
            </a>
          ))}

          <div className={styles.card}>
            <h3 className={styles.title}>New Post</h3>

            <Authenticator>
              <form onSubmit={handleCreatePost}>
                <fieldset>
                  <legend>Title</legend>
                  <input
                    defaultValue={`Today, ${new Date().toLocaleTimeString()}`}
                    name="title"
                  />
                </fieldset>

                <fieldset>
                  <legend>Content</legend>
                  <textarea
                    defaultValue="I built an Amplify project with Next.js!"
                    name="content"
                  />
                </fieldset>

                <button>Create Post</button>
                <button type="button" onClick={() => Auth.signOut()}>
                  Sign out
                </button>
              </form>
            </Authenticator>
          </div>
        </div>
      </main>
    </div>
  );
}

Result of cold start after publishing :

image

Okay here we are already at almost 7 seconds of cold start.

So after following the documentation, cold start is already too high after second step, showing that Amplify NextJs SRR is not exploitable for a professional use, unless there is a trick to fix that.

If you want to check the project, everything is accessible here : https://github.com/vincent38wargnier/test-amplify-cold-start-nextjs-ssr

@nadetastic do you have any idea if we can expect a fix from the Amplify team, and if so, how long should it take ? Otherwise I will have to move on another technology sadly.

Thank you.

PS: here is the link of the current testing env if you want to play with it. https://master.d2jftjwuwoe0y8.amplifyapp.com/

And EDIT from my previous answer : Yes the same cold start is visible in localhost when we work directly with the online environment :

image
jwang-lilly commented 1 year ago

@vincent38wargnier, I greatly appreciate your thorough analyses. In this issue , it was mentioned the cold start was less dramatic when using next 13 app folder. It is still a couple of seconds. I tried to move my component to app folder but had problems placing Amylify.configure in either layout.jsx or index.jsx. My app from time to time complains about no credentials, but not all the time though. No such problem when using the pages folder. I am puzzled that amplify team has pretty much done nothing for the above issue for two months.

nadetastic commented 1 year ago

@vincent38wargnier @JianWang2016 thanks for the additional information on this issue, very much appreciated.

I've been able to experience the similar cold start times with next@13 and next@12 and I'm discussing this with the team - will follow up here soon

gornostal commented 1 year ago

Is there any workaround to this? I have the same issue too. Thanks!

simotissi commented 1 year ago

Same problem here. About 20sec for the first load.

Gere-y-mir commented 1 year ago

+1

nadetastic commented 1 year ago

Hi @gornostal @simotissi - can you confirm if this is happening only after deploying to Hosting or also on localhost?

marcantoineveilleux commented 1 year ago

For me, it's only while hosting. Localhost is fine.

vincent38wargnier commented 1 year ago

I also thought it was on hosting only but I noticed if I restart my app after a while on localhost I have the same cold start unless everything is mocked

nadetastic commented 1 year ago

Thanks @vincent38wargnier - for issues in local host, is it after running next build && next start or next dev ?

simotissi commented 1 year ago

Yes @nadetastic , it just seems like a problem on Hosting. In localhost it is definitely faster, even if not immediate

dylan-westbury commented 1 year ago

We have a super basic static next.js web app that doesn't even call Amplify.configure and it's taking 20 seconds on first cold start load.

Here is link: https://feature-landingpage.d16t4qlpm725tl.amplifyapp.com/

Screenshot 2023-04-11 at 10 44 14 am

The project is in a Lerna / NX monorepo (not sure if this would affect anything).

  "scripts": {
    "dev": "NODE_OPTIONS='--inspect' next dev",
    "build": "next build",
    "build:analyze": "ANALYZE=true next build",
    "start": "next start",
    "lint": "next lint",
    "precommit": "lint-staged"
  },
  "dependencies": {
    ...
    "@next/bundle-analyzer": "^13.2.4",
    "@types/node": "18.15.3",
    "@types/react": "18.0.28",
    "@types/react-dom": "18.0.11",
    "@webiny/react-rich-text-renderer": "^5.34.6",
    "eslint": "8.36.0",
    "eslint-config-next": "13.2.4",
    "next": "13.2.4",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "typescript": "5.0.2"
  },
nodeover commented 1 year ago

I'm having the same problem too. I hope this gets resolved soon.

up1io commented 1 year ago

+1 I have the same problem.

abepuentes commented 1 year ago

So this has state the same from Feb 17th, does anyone try this builds on SST? just wondering if there's better cold starts time.

nadetastic commented 1 year ago

Related Hosting issue #3211

vincent38wargnier commented 1 year ago

It appears that cold start issues are prevalent in Next.js. The Next.js blog provides some improvements for cold starts in version 13 nextjs blog :

image

Apparently, when using getServerSideProps, it takes at least 1.8 seconds for a cold start.

I have rebuilt my backend using Nest.js, yet I still experience cold starts that seem to be related to the content of my frontend website and the utilization of getServerSideProps.

Additionally, the time taken by the Amplify backend for authentication further increases the cold start by a few seconds at a minimum.

In conclusion, I believe there is an incompatibility between using serverless with Next.js and an Amplify backend. Generally speaking, Next.js seems to be somewhat incompatible with serverless when getServerSideProps is needed.

Personally, I will be migrating my project to a microservice architecture and will wait until serverless technologies become more suitable for web NextJs requirements.

We can read in many blogs that cold start is an issue with NextJs : https://github.com/orgs/vercel/discussions/427 https://www.reddit.com/r/nextjs/comments/ml4i2t/ssr_pages_cold_start_improve_performance/

punit1108 commented 1 year ago

Facing the same issues, Though moving to Vercel helps this situation a lot. I noticed that there is almost no cold start there.

abepuentes commented 1 year ago

As a follow up I did migrate my project to SST and its working great, so if anyone need this resolve today just follow the migrate from Vercel guide on SST website and add 2 warm functions in the sst.config file. This will be a new deployment so you can keep you amplify hosting up for comparison. Btw our bill from just building on amplify hosting it was not as cheap as I first thought.

haruharuharuby commented 1 year ago

I'm currently facing the problem and maybe would resolved as the workaround.

With assuming the cause of this comes from the AWS Lambda Cold Start that including in the Amplify Hosting. In my case by configuring the Route 53 Health Check to ping constantly to the CloudFront domain.

Related Post: https://tobinc.medium.com/speeding-up-aws-amplify-nextjs-first-render-cold-start-and-images-an-unexpected-result-36a416d69615

tmb5cg commented 1 year ago

I'm having the same issue, and replicated it by removing the Amplify library. Without the Amplify library, the cold start load is still at least 2 seconds. With Amplify library, it's 6 seconds or more.

Given that any page load greater than 1 second or something leads to crazy drops in traffic, I can only imagine how this has hurt my website (edit: that actually generates revenue, now the more I think about how many users bailed because of first load, the angrier i'm getting). I always thought it was something I was doing wrong, but I sorta blindly trusted Amplify.

Huge bummer. Right when I finally understand Amplify really well, comfortable to build anything with users / user data etc sorta complex from the ground up in a weekend, I'm thinking I've wasted my time and should've learned vercel.

does anyone know of any tutorials on migrating away from Amplify?

abepuentes commented 1 year ago

Hey @tmb5cg this comment hit home, I can totally relate. To me the smoother path has been using SST, two commands to deploy the site using theirs migrate from Vercel guide and for free. They have guides to build all the amplify services in a performant way but the warm function option added a couple of weeks ago give much better TTFB.

tmb5cg commented 1 year ago

Hey @tmb5cg this comment hit home, I can totally relate. To me the smoother path has been using SST, two commands to deploy the site using theirs migrate from Vercel guide and for free. They have guides to build all the amplify services in a performant way but the warm function option added a couple of weeks ago give much better TTFB.

appreciate it, our shared condolences!

in theory my site is a simple react/nextJS app that can deploy anywhere if I strip the amplify auth. the only thing I need amplify for is:

And account creation is behind a Stripe check to confirm payment via webhook, boom then we hit the create user, which has nothing to do with amplify but for the api call to create user.

Now that I think about it, this is as simple a migration as one could want.

one interesting thing. I am building a desktop app in Electron where I sorta taped on an Amplify backend built for a website that will never exist. it works perfectly and for a desktop app, i'm not at the mercy of amplify serving the pages, the Amplify backend actually works really nicely.

Question: in theory I wonder how a NextJS app with the amplify package would perform deployed on Vercel, if it's Amplify's cold start that's causing all these problems. although at the core of our problem, is it not our app being "serverless" itself that is the issue? and vercel is serverless too? sorta confusing wording but hopefully what i'm trying to say makes sense.

either way i'm going to try to drop Amplify. sad that this will waste a whole sunday or more purely as a test but, can't emphasize enough the absolute most important thing on a website is its first load time. I unconciously bail from sooo many websites if they're not served instantly! 7 seconds, what the hell!

abepuentes commented 1 year ago

@tmb5cg totally relate again, we do use amplify as a backend for our apps and works great. Give a try to SST, this should not take more than 10 min.

// Run the following command in your root folder  
npx create-sst@latest
// Add the warmer functions to the config file sst.config.ts
// 50 warmer functions cost 1 dollar total on AWS, our project is small 2 is fine for us.
const site = new NextjsSite(stack, "site", {
        warm: 2,
      });
// Deploy to AWS, first time take a while. --stage can be dev or prod or whatever
npx set deploy --stage prod

Also I'm adding this two env variables to the .env file, its seems to make a difference to the open_next adapter, this do not work on AWS Amplify Hosting.

__NEXT_PRIVATE_PREBUNDLED_REACT = "next"
OPEN_NEXT_MINIFY=true

One last comment Amplify Hosting cost for building time for this single site, was around USD$ 8 a month, that was another reason to move away. So far has been free of charge on SST.

Cons:

abdallahshaban557 commented 1 year ago

Hello everyone, the Amplify Hosting team is currently working on improving the cold start times - we will provide updates when we have them on this issue.

Tomekmularczyk commented 1 year ago

Hey guys I experience the same problem when using Vercel and Amplify deployments. This is related to aws-amplify/amplify-js#11030

Here is a very basic repo reproducing the problem: https://github.com/Tomekmularczyk/amplify-next and here is the recording:

https://github.com/aws-amplify/amplify-js/assets/12544704/6807fc40-4f9a-4515-83c0-3d8faf2a07c7

  1. Deploy the above site to Vercel or AWS
  2. Go to link {URL}/en
  3. Notice it take initially ~6s to load the page

Note that:

@abdallahshaban557 should I create separate issue as this is somewhat different setup than what has been discussed here and it doesn't matter if it is AWS or Vercel hosting - delay happens in both.

tmb5cg commented 1 year ago

Hi all,

So I migrated hosting for two of my Anplify apps to Vercel. They function identically as before and load in less than 1 second compared to 6-12 seconds previously.

My backend is still entirely Amplify and it's a great product for that. I just hardcoded my keys which I know isn't great but I only use one backend environment so each deploy, both to the frontend or backend, doesn't break anything.

I'm not sure what the issue others encountered, if someone can explain how my keys would change (like as in aws-exports passed into Amplify.configure) because it works great now.

I can't imagine how much traffic / potential customers I missed out on but it's been a great learning process either way (the exact stat is like 40% of users bail after 3 seconds and I 100% believe that).

I really like Vercel's dashboard too, it's like having Amplify Studio backend visualizer except it's Vercel studio for your frontend. And you can integrate page speed + more cool stuff, and learn a new platform at the same time.

My understanding is that Amplify is incredible as an all in one backend builder, correct me if I'm wrong, but as an all in one platform it's really meant as a test proof of concept. So naturally splitting the hosting/frontend from the backend in the end I have a really great setup (let's see if I eat my words lol)

I am SO glad I found this thread, not sure how I stumbled on it because up until a week ago I was still dead convinced I was doing something wrong / created a totally dependency bloated project (which I rebuilt from scratch like 3 or 4 times in new Amplify environments attempting to fix what I now know is unfixable). Just searching "amplify next js react very slow first time to load" on Google, you'd never find it's a very real thing.

Edit 7/6/23: my sales/revenue have jumped 275% month over month (no joke) on one of my Amplify apps since I migrated the frontend to Vercel. Also my Google impressions spiked by a lot, even though previously I had a good PageSpeed score (which I never understood) with Amplify, now it's actually flat 100s

fnavarrodev commented 1 year ago

Those who can not pay Vercel I highly recommend SST. We moved our next.js apps from Amplify to SST. https://docs.sst.dev/start/nextjs The option to warm the lambda is a configuration flag but can't be used with Lambda@Edge, that in our case works better using Edge location. Give it a try. I'm not the first here in this thread recommending it.

JakubBatel commented 1 year ago

Hi everyone!

First of all, I would like to thank everyone who commented here it was a tremendous help and moral boost that I am not alone in this.

I would like to add my insight and recommend Netlify if your budget is tight (can not afford Vercel) and you are too lazy to play around with SST. It works great, deployment is super easy and works out of the box without any cold starts. And the best thing is that their free plan can be actually used for commercial use.

So if you are like me and building a portfolio website or any sort of small website I believe that Netlify is the best option for you.

I had one issue which I fixed sort of quickly and that is with i18n I got Too Many Redirects because Netlify setups some redirects on its own and NextJS middleware also tried to redirect so it ended in an infinite loop redirecting from {URL} to {URL}/en and then the other way around. I fixed that by turning on the language prefix for the default language as well.

nadetastic commented 1 year ago

Hello everyone, quick update on this, the Amplify Hosting team is currently working on improving the cold start times and are tracking this work on this issue in the Hosting repo. We will continue to provide updates here but please feel free to subscribe to that issue for updates directly from the Hosting team.

calavera commented 1 year ago

Hey everyone 👋

We just released some changes to improve how long it takes to serve content from Next.js apps. These changes require a new deploy in your application to take effect. The expected outcome is that your sites should load quicker than before.

If you have comments or questions don't hesitate to reach us via AWS support.

adamicska commented 1 year ago

Hello @calavera and @nadetastic, thanks for the update! Redeployed the app as suggested, but I'm still experiencing 4.5-6.5 sec cold starts....

tmb5cg commented 1 year ago

Hello @calavera and @nadetastic, thanks for the update! Redeployed the app as suggested, but I'm still experiencing 4.5-6.5 sec cold starts....

Switch to vercel for frontend hosting, I've seen a 50% increase in traffic (no joke) and it is free

vishalobrizum commented 1 year ago

Hello, I followed the instructions and redeployed but I am seeing 15 seconds delay 😢 . At this rate, this is not usable in production. I am using Amplify to host the app. It's a nextjs 13 app directory app:

Screenshot 2023-08-09 at 8 05 36 PM

Any help would be greatly appreciated!!

ConorFl commented 1 year ago

Still seeing significant cold start delays (aws-amplify 5.3.8, next 13.4.16). I was able to solve it with the health check suggested above, but paying a dollar month to make my code work is a bummer.

adarsh-drishya commented 11 months ago

hi everyone , https://nextjs.org/docs/app/api-reference/next-config-js/optimizePackageImports use it, i saw significant improvement

Tomekmularczyk commented 11 months ago

hi everyone , https://nextjs.org/docs/app/api-reference/next-config-js/optimizePackageImports use it, i saw significant improvement

can you share the exact config you use?

adarsh-drishya commented 11 months ago

first of all it is released yesterday @Tomekmularczyk so just update your nextjs version to 13.5.2 , then do the above

Tomekmularczyk commented 11 months ago

first of all it is released yesterday @Tomekmularczyk so just update your nextjs version to 13.5.2 , then do the above

can you share the exact code?

aprilmintacpineda commented 10 months ago

Closed even though not fixed. Typical move of AWS Amplify. That's why I stopped using this tool. They really cannot fix this because using docker for aws lambda will inevitably increase your cold-start. The only solution is to not use docker but you can't do that with NextJS.

kitdesai commented 10 months ago

why was this closed? this is definitely NOT fixed. I am still experiencing these issues with Amplify and my Next.js app running the latest version. I guess I need to try Vercel or SST instead?

tmb5cg commented 10 months ago

why was this closed? this is definitely NOT fixed. I am still experiencing these issues with Amplify and my Next.js app running the latest version. I guess I need to try Vercel or SST instead?

The longer you wait the more customers you're losing lol

vincent38wargnier commented 10 months ago

why was this closed? this is definitely NOT fixed. I am still experiencing these issues with Amplify and my Next.js app running the latest version. I guess I need to try Vercel or SST instead?

I gave up wih serverless for backend. I'm using classical micro service, and Vercel for Serverless Front. And even like that I have like 3sec cold start, cause you need to optimize your front as f*ck to reduce cold start using SSR. But cold start is definitly shorter on Vercel

RoseSecurity commented 9 months ago

Any way we could reopen this ticket? My Next.js app is crying out in pain from how cold the start is

➜  ~ curl -s --connect-timeout 5 -w "time_namelookup: %{time_namelookup}, time_connect: %{time_connect},
time_appconnect: %{time_appconnect}, time_pretransfer: %{time_pretransfer}, time_redirect: %{time_redirect},
time_starttransfer: %{time_starttransfer}, 
time_total: %{time_total}\n" -o /dev/null https://whywasthisticketclosed.com

time_namelookup: 0.195355
time_connect: 0.223631
time_appconnect: 0.266611
time_pretransfer: 0.266858
time_redirect: 0.000000
time_starttransfer: 11.731117
time_total: 11.740227
JakubBatel commented 9 months ago

I am glad I decided to switch to Netlify (6 months ago). From time to time I get an email about updates on this issue. So I check it out just out of curiosity and I have to say that I don't regret ditching the AWS Amplify as even a half year later the most basic functionality like loading a website in less then 4 seconds is still impossible. This is miles away to be production ready.

github-actions[bot] commented 9 months ago

This issue has been automatically locked.

mauerbac commented 8 months ago

Hey folks - Matt from the Amplify Hosting team. I see the comments that this issue has reappeared for some of you. Going to investigate with the team.