You log in · Lambda + RDS MySQL

10 steps from your browser to the database and back.

No background job: logging in doesn't change any todos. Try Create, Update or Delete.

InternetAWS Region · us-east-1VPCPrivate subnet · no internetYour browseron the internetAPI GatewayHTTP API · front doorCloudWatch Logsapp log linesLambda functionruns once per requestENIfunction's network cardRDS MySQLdatabase: todoioYou log in1Into the front door2Wake up the function3Read the form4Step into the VPC5Ask the database6The database answers7Check the password8Back 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.
    • 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. You log in. Path: Your browser. Your browser sends POST /login over HTTPS.
  2. 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.
  3. 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.
  4. Read the form. Path: Lambda function. The app reads your email and password. You're a customer of Todo.io, not an IAM user, so AWS has no idea who you are.
  5. 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.
  6. 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.users → allow.
  7. The database answers. Path: RDS MySQL → ENI → Lambda function. MySQL returns your user row, including the stored password hash.
  8. Check the password. Path: Lambda function. The app hashes the password you typed and compares it with the stored hash. They match, so it starts a session for you. Checks: app: Password hash matches → allow.
  9. Back to you. Path: Lambda function → API Gateway → Your browser. You get 200 OK plus a session cookie, so your next requests prove who you are.
  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. Your browser sends POST /login over HTTPS.

    Show me the real thing

    The HTTP request

    POST /login HTTP/1.1
    Host: abc123.execute-api.us-east-1.amazonaws.com
    Content-Type: application/json
    
    {"email":"sam@example.com","password":"••••••••"}
  2. The request arrives at API Gateway, a managed HTTPS front door. There's no server or firewall for you to look after.

  3. 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.

  4. The app reads your email and password. You're a customer of Todo.io, not an IAM user, so AWS has no idea who you are.

    Exam tipYour app's customers are never IAM principals. IAM is for the people and software that manage or call AWS itself.

  5. 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.

  6. 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.usersAllowed
    Show me the real thing

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

    SELECT id, password_hash FROM users WHERE email = 'sam@example.com';

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

  7. MySQL returns your user row, including the stored password hash.

  8. The app hashes the password you typed and compares it with the stored hash. They match, so it starts a session for you.

    • ✓App Password hash matchesAllowed
  9. You get 200 OK plus a session cookie, so your next requests prove who you are.

    Show me the real thing

    The HTTP response

    HTTP/1.1 200 OK
    Set-Cookie: session=eyJ1c2VySWQiOiJ1LTEyMyJ9.Zm9v; HttpOnly; Secure
  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 POST /login 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).
  • You, the customer, were never an IAM user. IAM controls the app, not its customers.