SAM Resource Types

The SAM Template's Serverless Resource Types

SAM 24 adds 13 AWS 24 ::Serverless::* types. The ones BookNest-sized applications use most:

Frequently used AWS SAM resource types
SAM type Expands into
Function Lambda 24 function, execution role, event sources and permissions
Api, HttpApi, WebSocketApi API Gateway 24 REST, HTTP or WebSocket API, stage, deployment
SimpleTable DynamoDB 24 table with one primary key, on-demand billing
LayerVersion Lambda layer version
StateMachine Step Functions 24 state machine and its role
Connector IAM policies that let one resource call another
Application A nested stack from the Serverless Application Repository

The others are GraphQLApi (AppSync 24 ), CapacityProvider, MicrovmImage and NetworkConnector. A Globals section sets defaults for every function, and policy templates such as DynamoDBReadPolicy generate least-privilege statements for a named table:

sam/template.yaml: BookNest's catalog API in SAMYAML
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: BookNest's catalog API as a SAM application
Globals:
  Function:
    Runtime: nodejs24.x
    MemorySize: 256
    Timeout: 10
Resources:
  BooksTable:
    Type: AWS::Serverless::SimpleTable
    Properties:
      TableName: booknest-sam-books
      PrimaryKey: {Name: id, Type: Number}
  BooksFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: src/
      Handler: books.handler
      Environment:
        Variables:
          BOOKS_TABLE: !Ref BooksTable
          DYNAMODB_ENDPOINT: ""
      Policies:
        - DynamoDBReadPolicy: {TableName: !Ref BooksTable}
      Events:
        ListBooks: {Type: Api, Properties: {Path: /books, Method: get}}
        GetBook: {Type: Api, Properties: {Path: "/books/{id}", Method: get}}
Outputs:
  BooksApi:
    Value: !Sub >-
      https://${ServerlessRestApi}.execute-api.${AWS::Region}.${AWS::URLSuffix}/Prod
sam/src/books.mjs: one handler for both routesJavaScript
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, GetCommand, ScanCommand } from "@aws-sdk/lib-dynamodb";
const endpoint = process.env.DYNAMODB_ENDPOINT || undefined;
const db = DynamoDBDocumentClient.from(new DynamoDBClient({ endpoint }));
const TableName = process.env.BOOKS_TABLE;
const json = (statusCode, body) => ({
  statusCode, headers: { "content-type": "application/json" }, body: JSON.stringify(body),
});
export const handler = async (event) => {
  const id = event.pathParameters?.id;
  if (id === undefined) {
    const { Items } = await db.send(new ScanCommand({ TableName }));
    const books = Items.map(({ id, title, price }) => ({ id, title, price }));
    return json(200, books.sort((a, b) => a.id - b.id));
  }
  if (!/^\d+$/.test(id)) return json(400, { error: "id must be an integer" });
  const { Item } = await db.send(new GetCommand({ TableName, Key: { id: Number(id) } }));
  return Item ? json(200, Item) : json(404, { error: "book not found" });
};

DYNAMODB_ENDPOINT is empty in the cloud, where the SDK finds DynamoDB itself (LocalStack 63,725 injects its endpoint into the functions it runs), and is overridden only for local runs. src/package.json declares the module type; the runtime already provides the AWS SDK.