
Serverless Architecture
- 412 installs
- 305 repo stars
- Updated March 4, 2026
- aj-geddes/useful-ai-prompts
serverless-architecture is an agent skill that designs serverless backends with functions, event triggers, queues, and managed data stores for developers who need cost-efficient, low-ops API and worker systems.
About
serverless-architecture is an agent skill from aj-geddes/useful-ai-prompts that guides design of event-driven, function-based backends. The skill maps HTTP and async triggers to compute units, connects queues and streams for decoupled workers, and selects managed databases and object stores for minimal operations overhead. Developers reach for serverless-architecture when scoping APIs, webhooks, or batch pipelines that should scale on demand without maintaining servers. Outputs include component diagrams, trigger-to-function mappings, and cost-versus-ops tradeoff notes for the chosen cloud primitives.
- Models event-driven flows with queues, streams, and schedulers
- Selects FaaS, API Gateway, and managed database pairings
- Addresses cold starts, idempotency, and observability patterns
- Estimates cost and scaling behavior per workload profile
Serverless Architecture by the numbers
- 412 all-time installs (skills.sh)
- Ranked #387 of 1,039 Cloud & Infrastructure skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/aj-geddes/useful-ai-prompts --skill serverless-architectureAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 412 |
|---|---|
| repo stars | ★ 305 |
| Last updated | March 4, 2026 |
| Repository | aj-geddes/useful-ai-prompts ↗ |
How do you design a serverless backend architecture?
Design serverless backends with functions, event triggers, queues, and managed data stores optimized for cost, scale, and ops minimalism.
Who is it for?
Backend developers architecting event-driven APIs or workers who want function-based compute with managed queues and databases.
Skip if: Teams requiring long-running processes, persistent local state, or full control over VM networking and kernel configuration.
When should I use this skill?
A developer asks to architect serverless APIs, wire event triggers to functions, or choose managed stores for a low-ops backend.
What you get
Serverless component diagram, event trigger map, queue topology, and managed data store selection.
- Architecture diagram
- Event trigger mapping
Files
Serverless Architecture
Table of Contents
Overview
Serverless architecture enables building complete applications without managing servers. Design event-driven, scalable systems using managed compute services, databases, and messaging systems. Pay only for actual usage with automatic scaling.
When to Use
- Event-driven applications
- API backends and microservices
- Real-time data processing
- Batch jobs and scheduled tasks
- Workflow automation
- IoT data pipelines
- Multi-tenant SaaS applications
- Mobile app backends
Quick Start
Minimal working example:
# serverless.yml - Serverless Framework
service: my-app
frameworkVersion: "3"
provider:
name: aws
runtime: nodejs18.x
region: us-east-1
stage: ${opt:stage, 'dev'}
memorySize: 256
timeout: 30
environment:
STAGE: ${self:provider.stage}
DYNAMODB_TABLE: ${self:service}-users-${self:provider.stage}
SNS_TOPIC_ARN: arn:aws:sns:${self:provider.region}:${aws:accountId}:my-topic
httpApi:
cors: true
iam:
role:
statements:
- Effect: Allow
Action:
- dynamodb:Query
- dynamodb:Scan
// ... (see reference guides for full implementation)Reference Guides
Detailed implementations in the references/ directory:
| Guide | Contents |
|---|---|
| Serverless Application Architecture | Serverless Application Architecture |
| Event-Driven Lambda Handler Pattern | Event-Driven Lambda Handler Pattern |
| Orchestration with Step Functions | Orchestration with Step Functions |
| Monitoring and Observability | Monitoring and Observability |
Best Practices
✅ DO
- Design idempotent functions
- Use event sources efficiently
- Implement proper error handling
- Monitor with CloudWatch/Application Insights
- Use infrastructure as code
- Implement distributed tracing
- Version functions for safe deployments
- Use environment variables for configuration
❌ DON'T
- Create long-running functions
- Store state in functions
- Ignore cold start optimization
- Use synchronous chains
- Skip testing
- Hardcode configuration
- Deploy without monitoring
Event-Driven Lambda Handler Pattern
Event-Driven Lambda Handler Pattern
// src/handlers/processUserCreated.js
const AWS = require("aws-sdk");
const dynamodb = new AWS.DynamoDB.DocumentClient();
const userService = require("../services/userService");
const emailService = require("../services/emailService");
exports.handler = async (event, context) => {
console.log("Processing user created event:", JSON.stringify(event));
try {
// Parse SNS message
const records = event.Records;
for (const record of records) {
const message = JSON.parse(record.Sns.Message);
const userId = message.userId;
// Get user details
const user = await userService.getUser(userId);
// Send welcome email
await emailService.sendWelcomeEmail(user);
// Initialize user preferences
await dynamodb
.put({
TableName: process.env.DYNAMODB_TABLE,
Item: {
id: userId,
preferences: {
newsletter: true,
notifications: true,
},
createdAt: Date.now(),
},
})
.promise();
// Log success
console.log(`Successfully processed user creation for ${userId}`);
}
return {
statusCode: 200,
body: JSON.stringify({ message: "Processed" }),
};
} catch (error) {
console.error("Error processing event:", error);
throw error; // SNS will retry
}
};
// src/handlers/processImageUpload.js
const AWS = require("aws-sdk");
const s3 = new AWS.S3();
const rekognition = new AWS.Rekognition();
exports.handler = async (event, context) => {
try {
for (const record of event.Records) {
const bucket = record.s3.bucket.name;
const key = record.s3.object.key;
console.log(`Processing image: s3://${bucket}/${key}`);
// Analyze image with Rekognition
const labels = await rekognition
.detectLabels({
Image: {
S3Object: {
Bucket: bucket,
Name: key,
},
},
MaxLabels: 10,
MinConfidence: 70,
})
.promise();
// Create thumbnail
await createThumbnail(bucket, key);
// Index metadata
await indexMetadata(bucket, key, labels);
console.log(`Completed processing ${key}`);
}
} catch (error) {
console.error("Error processing S3 event:", error);
throw error;
}
};
async function createThumbnail(bucket, key) {
// Implementation
return true;
}
async function indexMetadata(bucket, key, labels) {
// Implementation
return true;
}Monitoring and Observability
Monitoring and Observability
# Monitoring helper
import json
import logging
from aws_lambda_powertools import Logger, Tracer, Metrics
from aws_lambda_powertools.utilities.typing import LambdaContext
logger = Logger()
tracer = Tracer()
metrics = Metrics()
@logger.inject_lambda_context
@tracer.capture_lambda_handler
def handler(event: dict, context: LambdaContext) -> dict:
try:
logger.info("Processing event", extra={"event": event})
# Add custom metrics
metrics.add_metric(
name="OrderProcessed",
unit="Count",
value=1
)
metrics.add_metric(
name="OrderAmount",
unit="None",
value=event.get('amount', 0)
)
# Business logic
result = process_order(event)
logger.info("Order processed successfully", extra={"orderId": result['orderId']})
return result
except Exception as e:
logger.exception("Error processing order")
metrics.add_metric(
name="OrderFailed",
unit="Count",
value=1
)
raise
finally:
metrics.flush()
def process_order(event):
return {"orderId": event.get("id"), "status": "completed"}Orchestration with Step Functions
Orchestration with Step Functions
{
"Comment": "Order processing workflow",
"StartAt": "ValidateOrder",
"States": {
"ValidateOrder": {
"Type": "Task",
"Resource": "arn:aws:lambda:region:account:function:validateOrder",
"Next": "CheckInventory",
"Catch": [
{
"ErrorEquals": ["InvalidOrder"],
"Next": "OrderFailed"
}
]
},
"CheckInventory": {
"Type": "Task",
"Resource": "arn:aws:lambda:region:account:function:checkInventory",
"Next": "InventoryDecision"
},
"InventoryDecision": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.inStock",
"BooleanEquals": true,
"Next": "ProcessPayment"
}
],
"Default": "OutOfStock"
},
"ProcessPayment": {
"Type": "Task",
"Resource": "arn:aws:lambda:region:account:function:processPayment",
"Next": "PaymentDecision",
"Retry": [
{
"ErrorEquals": ["PaymentError"],
"IntervalSeconds": 2,
"MaxAttempts": 3,
"BackoffRate": 2.0
}
]
},
"PaymentDecision": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.paymentApproved",
"BooleanEquals": true,
"Next": "ShipOrder"
}
],
"Default": "PaymentFailed"
},
"ShipOrder": {
"Type": "Task",
"Resource": "arn:aws:lambda:region:account:function:shipOrder",
"Next": "NotifyCustomer"
},
"NotifyCustomer": {
"Type": "Task",
"Resource": "arn:aws:states:::sns:publish",
"Parameters": {
"TopicArn": "arn:aws:sns:region:account:order-updates",
"Message": {
"orderId.$": "$.orderId",
"status": "shipped"
}
},
"Next": "OrderSuccess"
},
"OrderSuccess": {
"Type": "Succeed"
},
"OutOfStock": {
"Type": "Task",
"Resource": "arn:aws:lambda:region:account:function:notifyOutOfStock",
"Next": "OrderFailed"
},
"PaymentFailed": {
"Type": "Task",
"Resource": "arn:aws:lambda:region:account:function:handlePaymentFailure",
"Next": "OrderFailed"
},
"OrderFailed": {
"Type": "Fail",
"Error": "OrderFailed",
"Cause": "Order processing failed"
}
}
}Serverless Application Architecture
Serverless Application Architecture
# serverless.yml - Serverless Framework
service: my-app
frameworkVersion: "3"
provider:
name: aws
runtime: nodejs18.x
region: us-east-1
stage: ${opt:stage, 'dev'}
memorySize: 256
timeout: 30
environment:
STAGE: ${self:provider.stage}
DYNAMODB_TABLE: ${self:service}-users-${self:provider.stage}
SNS_TOPIC_ARN: arn:aws:sns:${self:provider.region}:${aws:accountId}:my-topic
httpApi:
cors: true
iam:
role:
statements:
- Effect: Allow
Action:
- dynamodb:Query
- dynamodb:Scan
- dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:DeleteItem
Resource: "arn:aws:dynamodb:${self:provider.region}:${aws:accountId}:table/${self:provider.environment.DYNAMODB_TABLE}"
- Effect: Allow
Action:
- sns:Publish
Resource: ${self:provider.environment.SNS_TOPIC_ARN}
functions:
# HTTP API endpoints
getUser:
handler: src/handlers/getUser.handler
events:
- httpApi:
path: /api/users/{id}
method: GET
listUsers:
handler: src/handlers/listUsers.handler
events:
- httpApi:
path: /api/users
method: GET
createUser:
handler: src/handlers/createUser.handler
events:
- httpApi:
path: /api/users
method: POST
# Event-driven functions
processUserCreated:
handler: src/handlers/processUserCreated.handler
events:
- sns:
arn: arn:aws:sns:${self:provider.region}:${aws:accountId}:user-created
topicName: user-created
processPendingOrders:
handler: src/handlers/processPendingOrders.handler
timeout: 300
events:
- schedule:
rate: cron(0 2 * * ? *)
enabled: true
# S3 event handler
processImageUpload:
handler: src/handlers/processImageUpload.handler
events:
- s3:
bucket: my-uploads-${self:provider.stage}
event: s3:ObjectCreated:*
rules:
- prefix: uploads/
- suffix: .jpg
# SQS queue processor
processQueue:
handler: src/handlers/processQueue.handler
events:
- sqs:
arn: arn:aws:sqs:${self:provider.region}:${aws:accountId}:my-queue
batchSize: 10
batchWindow: 5
resources:
Resources:
UsersTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: ${self:provider.environment.DYNAMODB_TABLE}
AttributeDefinitions:
- AttributeName: id
AttributeType: S
- AttributeName: createdAt
AttributeType: N
KeySchema:
- AttributeName: id
KeyType: HASH
- AttributeName: createdAt
KeyType: RANGE
BillingMode: PAY_PER_REQUEST
StreamSpecification:
StreamViewType: NEW_AND_OLD_IMAGES
UserNotificationTopic:
Type: AWS::SNS::Topic
Properties:
TopicName: user-created-${self:provider.stage}
ProcessingQueue:
Type: AWS::SQS::Queue
Properties:
QueueName: my-queue-${self:provider.stage}
VisibilityTimeout: 300
MessageRetentionPeriod: 1209600
plugins:
- serverless-python-requirements
- serverless-plugin-tracing
- serverless-offline
- serverless-dynamodb-local#!/bin/bash
# validate-config.sh - Validate infrastructure configuration
# Usage: ./validate-config.sh <config_file>
set -euo pipefail
CONFIG_FILE="${{1:?Usage: $0 <config_file>}}"
echo "Validating: $CONFIG_FILE"
# TODO: Add configuration validation logic
# - Check required fields
# - Validate syntax (YAML/JSON/HCL)
# - Verify referenced resources exist
# - Check for security best practices
echo "Validation complete."
# Infrastructure Configuration Starter
# TODO: Customize for your infrastructure setup
#
# Usage: Copy this file and modify for your environment
# --- Environment Configuration ---
environment: production
region: us-east-1
# --- Resource Definitions ---
# TODO: Add resource definitions specific to this skill's domain
# --- Security Settings ---
# TODO: Add security configuration
# --- Monitoring ---
# TODO: Add monitoring/alerting configuration
Related skills
FAQ
What components does serverless-architecture cover?
serverless-architecture designs compute functions, event triggers, message queues, and managed data stores as a cohesive backend. The skill outputs trigger mappings, queue flows, and storage choices optimized for scale and low operational overhead.
When should developers choose serverless over containers?
serverless-architecture favors bursty, event-driven workloads with managed scaling and minimal ops. The skill highlights when long-running processes, custom networking, or persistent local state make container platforms a better fit.