You open your todo list · Lambda + RDS MySQL

10 steps from your browser to the database and back.

Nothing to push: reading doesn't change anything. The live line just stays open.

InternetAWS Region · us-east-1VPCPrivate subnet · no internetYour browseron the internetAPI GatewayHTTP API · front doorAPI GatewayWebSocket API · live lineCloudWatch Logsapp log linesLambda functionruns once per requestENIfunction's network cardRDS MySQLdatabase: todoioThe live line is already open1You open your todo list2Into the front door3Wake up the function4Who are you?5Step into the VPC6Ask the database7The database answers8Back to you9Leave a note10

Text version of this diagram.

What sits where:

  • AWS Region · us-east-1: A Region is a part of the world where AWS has data centers. Most things you build live in one Region. us-east-1 is in northern Virginia. contains:
    • VPC: Virtual private cloud: your own private network inside AWS. Nothing gets in or out except the ways you allow. contains:
      • Private subnet · no internet: A slice of the VPC with no route to the internet at all. Nothing here can be reached from outside. contains:
        • ENI (function's network card): Elastic network interface: a virtual network card. It gives the function an address inside your VPC.
        • RDS MySQL (database: todoio): A MySQL database that AWS runs for you, including the server, patches and backups. todoio is the database's name.
    • API Gateway (HTTP API · front door): The front door for the app's web requests: it receives each one and hands it to your code. An HTTP API is its simple kind for ordinary requests.
    • API Gateway (WebSocket API · live line): The front door for the app's web requests. A WebSocket API keeps a connection open, so the server can push updates to your browser instantly.
    • CloudWatch Logs (app log lines): Collects the lines your app writes about what it's doing (its logs), so you can search them later.
    • Lambda function (runs once per request): Code that AWS runs only when a request arrives. No server to look after, and you pay per request.
  • Your browser (on the internet)

Steps, in order:

  1. The live line is already open. Path: Your browser → API Gateway. When you logged in, your browser opened a WebSocket to API Gateway. It stays open, so AWS can send you messages any time.
  2. You open your todo list. Path: Your browser. Your browser sends GET /todos over HTTPS.
  3. Into the front door. Path: Your browser → API Gateway. The request arrives at API Gateway, a managed HTTPS front door. There's no server or firewall for you to look after.
  4. Wake up the function. Path: API Gateway → Lambda function. API Gateway invokes your Lambda function and hands it the request as an event. Checks: iam: Lambda resource policy: API Gateway may invoke todo-api → allow.
  5. Who are you?. Path: Lambda function. The app checks your signed session cookie and finds your user id, u-123. This is the app's own login, not AWS.
  6. Step into the VPC. Path: Lambda function → ENI. The database lives in a private subnet of a VPC, so the function is attached to that VPC. AWS gives it an ENI (a network card) in the private subnet.
  7. Ask the database. Path: ENI → RDS MySQL. The app sends SQL to RDS MySQL in the private subnet on port 3306. It logs in with a database username and password, not with IAM. Checks: security-group: todo-db-sg: TCP 3306 from todo-lambda-sg → allow; mysql: MySQL user todo_app: SELECT on todoio.todos → allow.
  8. The database answers. Path: RDS MySQL → ENI → Lambda function. MySQL returns your 3 todos.
  9. Back to you. Path: Lambda function → API Gateway → Your browser. You get 200 OK with your todos, and the list appears.
  10. Leave a note. Path: Lambda function → CloudWatch Logs. Lambda sends what the function printed to CloudWatch Logs, so Todo.io's engineers can see what happened.
Step 1 of 10
Step 1 of 10
  1. When you logged in, your browser opened a WebSocket to API Gateway. It stays open, so AWS can send you messages any time.

    Show me the real thing

    The WebSocket handshake

    GET /prod HTTP/1.1
    Host: ws123.execute-api.us-east-1.amazonaws.com
    Upgrade: websocket
    Connection: Upgrade
    
    → API Gateway assigns connection id Ab3xYzEXAMPLE=

    Exam tipAn API Gateway WebSocket API has $connect, $disconnect and $default routes. Each one can call Lambda or an HTTP backend.

  2. Your browser sends GET /todos over HTTPS.

    Show me the real thing

    The HTTP request

    GET /todos HTTP/1.1
    Host: abc123.execute-api.us-east-1.amazonaws.com
    Cookie: session=eyJ1c2VySWQiOiJ1LTEyMyJ9.Zm9v
  3. The request arrives at API Gateway, a managed HTTPS front door. There's no server or firewall for you to look after.

  4. API Gateway invokes your Lambda function and hands it the request as an event.

    • 🔑IAM Lambda resource policy: API Gateway may invoke todo-apiAllowed
    Show me the real thing

    Resource-based policy on the function: who may call it

    {
      "Effect": "Allow",
      "Principal": {
        "Service": "apigateway.amazonaws.com"
      },
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:us-east-1:111122223333:function:todo-api",
      "Condition": {
        "ArnLike": {
          "AWS:SourceArn": "arn:aws:execute-api:us-east-1:111122223333:abc123/*"
        }
      }
    }

    Exam tipThis is a resource-based policy. It lives on the function and says who may call it, the opposite of a policy attached to a role.

  5. The app checks your signed session cookie and finds your user id, u-123. This is the app's own login, not AWS.

  6. The database lives in a private subnet of a VPC, so the function is attached to that VPC. AWS gives it an ENI (a network card) in the private subnet.

    Exam tipA Lambda ENI never gets a public IP, so a VPC-attached function can't reach the internet, even from a public subnet. It needs a NAT gateway. Classic exam trap.

  7. The app sends SQL to RDS MySQL in the private subnet on port 3306. It logs in with a database username and password, not with IAM.

    • 🛡Security group todo-db-sg: TCP 3306 from todo-lambda-sgAllowed
    • 🗄MySQL MySQL user todo_app: SELECT on todoio.todosAllowed
    Show me the real thing

    The SQL (real code sends the values as parameters, never pasted into the string)

    SELECT id, title, done FROM todos WHERE user_id = 'u-123' ORDER BY created_at;

    Exam tipA security group rule can use another security group as its source: "anything wearing todo-lambda-sg may connect". Exam favourite.

  8. MySQL returns your 3 todos.

  9. You get 200 OK with your todos, and the list appears.

    Show me the real thing

    The HTTP response

    HTTP/1.1 200 OK
  10. Lambda sends what the function printed to CloudWatch Logs, so Todo.io's engineers can see what happened.

    Show me the real thing

    The log line

    2026-10-11T18:42:07Z INFO GET /todos user=u-123 status=200 14ms

    Exam tipLambda sends whatever your function prints to CloudWatch Logs automatically, as long as the execution role allows logs:PutLogEvents.

What to notice

  • There is no server at all. API Gateway takes the request and Lambda runs your code only when one arrives.
  • IAM never checked your SQL. MySQL has its own users; IAM only manages the database server itself.
  • The database sits in a private subnet with no route to the internet. Only the security groups you allowed can reach it.
  • The database password lives in the app config here. In production it belongs in Secrets Manager (Level 1).
  • To reach a database in a VPC, the function had to be attached to that VPC.
  • Every Lambda copy opens its own MySQL connection, and a traffic spike can exhaust them. RDS Proxy pools connections (Level 2).
  • A WebSocket stays open, so the server side can send you updates without you asking.
  • You, the customer, were never an IAM user. IAM controls the app, not its customers.