Ferdinand Frank
Ferdinand Frank

Reputation: 365

Serverless Lambda function runs into a timeout when running Nuxt

I just managed to deploy my Nuxt application via Serverless on AWS. Basically everything works as expected but in some cases the Lambda function just runs into a timeout and can't serve my Nuxt application. Since my application is a SPA the timeout only happens during a refresh of the browser window or when I visit my page in a new tab, but only sometimes. I already increased the Lambda timeout to 30s (meets the timeout of the API Gateway) which should be enough but the timeout still occurs.

Here's my serverless.yml:

service:
  name: test-app

plugins:
  - serverless-nuxt-plugin
  - serverless-dotenv-plugin
  - serverless-domain-manager

resources:
  Resources:
    AssetsBucket:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: ${self:custom.nuxt.bucketName}
        CorsConfiguration:
          CorsRules:
            - AllowedMethods:
                - GET
                - HEAD
              AllowedOrigins:
                - "*"

provider:
  name: aws
  region: eu-central-1 # this field is used for the assets files s3 path.
  stage: ${env:APP_ENV}
  runtime: nodejs12.x
  environment:
    NODE_ENV: ${env:APP_ENV}
  tags: # Optional service wide function tags
    usecase: test-app
    environment: ${self:provider.stage}
    domain: ${env:DEPLOY_DOMAIN}

custom:
  nuxt:
    version: app-${self:provider.stage}-v1
    bucketName: test-app-static-${self:provider.stage}
    cdnPath: https://cdn.XXX.com
  customDomain:
    domainName: ${env:DEPLOY_DOMAIN}
    certificateName: ${'*.'}${env:DEPLOY_DOMAIN}
    createRoute53Record: true
    endpointType: 'regional'

functions:
  nuxt:
    handler: lambda-handler.render
    memorySize: 512 # in MB with steps of 64
    timeout: 30 # in seconds
    events:
      - http: ANY /
      - http: ANY /{proxy+}

And my Lambda handler:

const awsServerlessExpress = require('aws-serverless-express');
const express = require('express');
const { Nuxt } = require('nuxt-start'); // eslint-disable-line
const nuxtConfig = require("./nuxt.config.js");
const app = express();

const nuxt = new Nuxt({
    ...nuxtConfig,
    dev: false,
    _start: true,
});
app.use(async (req, res) => {
    if (nuxt.ready) {
        await nuxt.ready()
    }
    nuxt.render(req, res)
});

const server = awsServerlessExpress.createServer(app, void 0, [
    'application/javascript',
    'application/json',
    'application/manifest+json',
    'application/octet-stream',
    'application/xml',
    'font/eot',
    'font/opentype',
    'font/otf',
    'image/gif',
    'image/jpeg',
    'image/png',
    'image/svg+xml',
    'image/x-icon', // for favicon
    'text/comma-separated-values',
    'text/css',
    'text/html',
    'text/javascript',
    'text/plain',
    'text/text',
    'text/xml',
    'application/rss+xml',
    'application/atom+xml',
]);

module.exports.render = (event, context) => {
    awsServerlessExpress.proxy(server, event, context);
};

Additionally, I setup a CloudFront distribution in front of my API Gateway to redirect http traffic to https. So nothing really special, I guess.

Here's an example of my CloudWatch logs that shows an example timeout:

So the duration of the Lambda is pretty distributed and I can't really understand why. I even found durations of 100ms but they can get up until the timeout of 30s. Is there anything wrong in my setup or something I missed? I'm aware of the cold start bottleneck for Lambdas but these timeout calls are not caused by a cold start.

I really appreciate your help!

Upvotes: 0

Views: 1610

Answers (1)

Ferdinand Frank
Ferdinand Frank

Reputation: 365

I currently solved the issue by increasing the memory limit first from 512MB to 1024MB and then on a second step from 1024MB to 2048MB.

See the CloudFront diagram here (blue line)

I guess that my application is just too large with too many dependencies and modules that need to be loaded when running the Lambda. However, I'm still not sure if a memory leak or something else is causing the issue and increasing the memory limit is just hiding the issue. But if anyone has the same issue, increasing the memory seems to be a good temporary fix to at least have your application available.

Upvotes: 0

Related Questions