Typical AWS lambda setup

This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the aws category.

Last Updated: 2024-04-27

How does a lambda heavy project look? Here's some observations from digging into a code-base and reading some textbooks on the topic:

Approach 1: Manual API endpoints

The typical setup is to use lambda functions attached to API endpoints.

Lambdas are often triggerred by standard HTTP requests like a normal web app

Remember here that CORS means that a (e.g.) a React.js browser app will not be allowed to talk to your API unless you add the appropriate permissions. Therefore the amazon API endpoints must have OPTIONS request ability in order to facilitate CORS requests containing specific headers e.g. Access-Control-Allow-Origin: *

Another way of stitching everything together is by subscribing to changes in an AmazonDynamoDB via a stream. Below is an explanation of DynamoDB.

Approach 2: Serverless Framework

It's a lot easier to use a framework to stitch all this stuff together than DIY in the console. Below are some examples with the serverless framework:

Here's an example config file:

service: candidate

frameworkVersion: ">=1.1.0 <2.0.0"

provider:
  name: aws
  runtime: nodejs4.3
  stage: dev
  region: us-east-1

functions:
  candidateSubmission:
    handler: api/candidates.submit
    memorySize: 128
    description: Submit candidate information and starts interview process.
    events:
      - http: 
          path: candidates
          method: post
   candidateDetails:
     handler: api/candidates.get
     events:
      - http:
          path: candidates/{id}
          method: get
          cors: true

What are the most important bits of info here?

Approach 3: DynamoDB

Some info on DynamoDB:

Here is an example setup for DynamoDB using the serverless framework

  service: usersCrud
  provider: aws
  functions:
  # Your Serverless function definitions go here.

  resources: # raw AWS::CloudFormation template syntax from here on.
    Resources:
      usersTable: 
        Type: AWS::DynamoDB::Table
        Properties:
          TableName: usersTable
          AttributeDefinitions:
            - AttributeName: email
              AttributeType: S
          KeySchema:
            - AttributeName: email
              KeyType: HASH
          ProvisionedThroughput:
            ReadCapacityUnits: 1
            WriteCapacityUnits: 1

This creates a usersTable with an email attribute that is of type string (S)

Next example: Let's provision a DynamoDB with certain iam role credentials:

provider:
  name: aws
  runtime: nodejs4.3
  stage: dev
  region: us-east-1
  environment:
    CANDIDATE_TABLE: ${self:service}-${opt:stage, self:provider.stage}
    CANDIDATE_EMAIL_TABLE: "candidate-email-${opt:stage, self:provider.stage}"
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:Query
        - dynamodb:Scan
        - dynamodb:GetItem
        - dynamodb:PutItem
      Resource: "*"

resources:
  Resources:
    CandidatesDynamoDbTable:
        TableName: ${self:provider.environment.CANDIDATE_TABLE}
        ...

Other tidbits

Resources