Hands-On Lab1,139 words

Hands-On Lab: Building a Loosely Coupled Serverless Architecture

Design scalable and loosely coupled architectures

Prerequisites

Before starting this lab, ensure you have the following ready:

  • AWS Account: An active AWS account with Administrator or PowerUser access.
  • AWS CLI Installed: The AWS Command Line Interface installed on your local machine.
  • AWS Credentials Configured: Run aws configure to set up your access keys, secret keys, and default region (e.g., us-east-1).
  • Basic Python Knowledge: Familiarity with basic Python syntax and JSON structures.
  • Zip Utility: A command-line zip tool to package your Lambda function.

Learning Objectives

By completing this lab, you will be able to:

  1. Design loosely coupled architectures by introducing a message broker (Amazon SQS) between components.
  2. Deploy stateless compute workloads using AWS Lambda.
  3. Manage API creation by configuring an Amazon API Gateway to trigger serverless functions.
  4. Demonstrate event-driven concepts where asynchronous background processing can scale independently from frontend requests.

Architecture Overview

In this lab, you will build a serverless architecture where a client sends an HTTP request to API Gateway. API Gateway routes the request to a stateless Lambda function (Producer), which then formats the payload and places it into an Amazon SQS Queue (Buffer).

This pattern prevents traffic spikes from overwhelming backend processing systems, achieving true loose coupling.

Loading Diagram...

Step-by-Step Instructions

Step 1: Create the Amazon SQS Queue

The first step to decoupling our application is creating the buffer—an Amazon Simple Queue Service (SQS) queue.

bash
aws sqs create-queue --queue-name brainybee-lab-queue

[!TIP] Save the QueueUrl returned in the output. You will need it to configure the Lambda function's environment variables in Step 3.

Console alternative
  1. Navigate to the Amazon SQS console.
  2. Click Create queue.
  3. Leave the type as Standard.
  4. Name the queue brainybee-lab-queue.
  5. Leave all other settings as default and click Create queue.

📸 Screenshot: The SQS creation success banner showing your new Queue URL.

Step 2: Create an IAM Role for the Lambda Function

AWS Lambda needs an execution role granting it permission to write logs to CloudWatch and send messages to your SQS queue.

First, create the trust policy document:

bash
cat > trust-policy.json <<EOF { "Version": "2012-10-17", "Statement": [ { "Action": "sts:AssumeRole", "Principal": { "Service": "lambda.amazonaws.com" }, "Effect": "Allow" } ] } EOF

Next, create the role and attach the necessary policies:

bash
# Create the role aws iam create-role \ --role-name brainybee-lambda-role \ --assume-role-policy-document file://trust-policy.json # Attach basic Lambda execution permissions (CloudWatch logs) aws iam attach-role-policy \ --role-name brainybee-lambda-role \ --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole # Attach SQS permissions aws iam attach-role-policy \ --role-name brainybee-lambda-role \ --policy-arn arn:aws:iam::aws:policy/AmazonSQSFullAccess
Console alternative
  1. Navigate to IAM > Roles > Create role.
  2. Select AWS service and choose Lambda as the use case. Click Next.
  3. Search for and check the boxes for AWSLambdaBasicExecutionRole and AmazonSQSFullAccess. Click Next.
  4. Name the role brainybee-lambda-role and click Create role.

Step 3: Deploy the Stateless Lambda Producer

Now we will write a stateless Python function that captures the API request and forwards it to the SQS queue.

Create the Python file:

bash
cat > lambda_function.py <<EOF import json import boto3 import os sqs = boto3.client('sqs') QUEUE_URL = os.environ['QUEUE_URL'] def lambda_handler(event, context): # Extract body from API Gateway event, or use a default message body = event.get('body', 'Hello from the BrainyBee decoupled architecture!') response = sqs.send_message( QueueUrl=QUEUE_URL, MessageBody=body ) return { 'statusCode': 200, 'body': json.dumps({ 'message': 'Successfully buffered in SQS!', 'messageId': response['MessageId'] }) } EOF

Zip the code and deploy the function (replace <YOUR_ACCOUNT_ID> and <YOUR_REGION> with your actual AWS details, or run the dynamic bash variables if using Linux/macOS):

bash
# Zip the deployment package zip function.zip lambda_function.py # Dynamically fetch the Queue URL and Account ID for the deployment QUEUE_URL=$(aws sqs get-queue-url --queue-name brainybee-lab-queue --query QueueUrl --output text) ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) # Create the function aws lambda create-function \ --function-name brainybee-lab-producer \ --runtime python3.9 \ --role arn:aws:iam::${ACCOUNT_ID}:role/brainybee-lambda-role \ --handler lambda_function.lambda_handler \ --zip-file fileb://function.zip \ --environment Variables="{QUEUE_URL=${QUEUE_URL}}"

[!NOTE] If you get an InvalidParameterValueException regarding the role, wait 10 seconds and try again. IAM role creation is eventually consistent.

Console alternative
  1. Navigate to the AWS Lambda console and click Create function.
  2. Name it brainybee-lab-producer, select Python 3.9 as the runtime.
  3. Under Permissions, choose Use an existing role and select brainybee-lambda-role.
  4. Click Create function.
  5. Scroll down to Code source, paste the Python code from above, and click Deploy.
  6. Go to the Configuration tab > Environment variables > Edit.
  7. Add a variable with Key: QUEUE_URL and Value: <your-sqs-queue-url>, then save.

Step 4: Configure API Gateway

To make our Lambda accessible over the web, we'll configure an HTTP API using Amazon API Gateway.

bash
REGION=$(aws configure get region) ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) # 1. Grant API Gateway permission to invoke your Lambda aws lambda add-permission \ --function-name brainybee-lab-producer \ --statement-id apigateway-invoke \ --action lambda:InvokeFunction \ --principal apigateway.amazonaws.com # 2. Create the HTTP API mapped directly to the Lambda function aws apigatewayv2 create-api \ --name brainybee-lab-api \ --protocol-type HTTP \ --target arn:aws:lambda:${REGION}:${ACCOUNT_ID}:function:brainybee-lab-producer

[!TIP] The output will contain an ApiEndpoint (e.g., https://xxxxxx.execute-api.us-east-1.amazonaws.com). Copy this URL.

Console alternative
  1. Navigate to the API Gateway console.
  2. Click Build under HTTP API.
  3. Click Add integration, select Lambda, and choose brainybee-lab-producer.
  4. Name the API brainybee-lab-api and click Next.
  5. Leave the route configuration as default (Method: ANY, Resource path: /brainybee-lab-producer). Click Next.
  6. Leave the stages as default ($default) and click Next, then Create.

📸 Screenshot: The invoke URL found on the API Gateway overview page.

Checkpoints

Let's verify that your loosely coupled architecture is working correctly.

Checkpoint 1: Invoke the API

Use curl (or your browser) to send a request to your API Gateway endpoint. Replace the URL with your specific ApiEndpoint from Step 4.

bash
curl -X POST https://<YOUR_API_ID>.execute-api.<REGION>.amazonaws.com/ \ -H "Content-Type: application/json" \ -d '"This is a test of a scalable, decoupled system!"'

Expected Output: {"message": "Successfully buffered in SQS!", "messageId": "..."}

Checkpoint 2: Verify the Message in the Buffer (SQS)

The API response was near-instant because Lambda didn't process the data; it simply dropped it in the queue. Now let's verify the message is safely stored in our SQS buffer.

bash
QUEUE_URL=$(aws sqs get-queue-url --queue-name brainybee-lab-queue --query QueueUrl --output text) aws sqs receive-message \ --queue-url ${QUEUE_URL} \ --max-number-of-messages 1

Expected Output: A JSON structure displaying your message body ("This is a test of a scalable, decoupled system!") and metadata. Because this is a decoupled architecture, this message will wait in the queue securely until a backend consumer instance is ready to process it.

Teardown

[!WARNING] Remember to run the teardown commands to avoid ongoing charges in your AWS account. While this lab primarily uses the AWS Free Tier, cleaning up is a vital cloud engineering habit.

Execute the following commands to destroy all provisioned resources:

bash
# 1. Delete API Gateway API_ID=$(aws apigatewayv2 get-apis --query "Items[?Name=='brainybee-lab-api'].ApiId" --output text) aws apigatewayv2 delete-api --api-id ${API_ID} # 2. Delete Lambda Function aws lambda delete-function --function-name brainybee-lab-producer # 3. Delete SQS Queue QUEUE_URL=$(aws sqs get-queue-url --queue-name brainybee-lab-queue --query QueueUrl --output text) aws sqs delete-queue --queue-url ${QUEUE_URL} # 4. Detach Policies and Delete IAM Role aws iam detach-role-policy --role-name brainybee-lambda-role --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole aws iam detach-role-policy --role-name brainybee-lambda-role --policy-arn arn:aws:iam::aws:policy/AmazonSQSFullAccess aws iam delete-role --role-name brainybee-lambda-role # 5. Clean up local files rm trust-policy.json lambda_function.py function.zip

Troubleshooting

ProblemPotential CauseSolution
InvalidParameterValueException: The role defined for the function cannot be assumed by Lambda.Eventual consistency in AWS IAM. The role was created but hasn't propagated globally yet.Wait 10-15 seconds and re-run the aws lambda create-function command.
Internal Server Error when calling the APIThe QUEUE_URL environment variable is missing or malformed in your Lambda configuration.Check the Lambda console under Configuration -> Environment variables. Ensure the value is a valid HTTPS SQS endpoint.
API Gateway returns {"message":"Forbidden"}You are using the wrong HTTP method or hitting the wrong route path.Check the route configured in API Gateway. If using the default CLI command above, hitting the root path (/) should work. Verify your ApiEndpoint.
aws: command not foundThe AWS CLI is not installed or not added to your system's PATH.Follow the AWS documentation to install the AWS CLI for your specific operating system, then run aws configure.

Ready to study AWS Certified Solutions Architect - Associate (SAA-C03)?

Practice tests, flashcards, and all study notes — free, no sign-up needed.

Start Studying — Free