Overview
Serverless architecture represents a cloud computing execution model where cloud providers manage server infrastructure, automatically allocate resources, and charge based on actual consumption rather than pre-allocated capacity. The term "serverless" describes the developer experience rather than the technical reality—servers still exist, but developers do not provision, maintain, or scale them directly.
The architecture emerged from the need to reduce operational overhead and improve resource efficiency in cloud environments. Amazon Web Services introduced AWS Lambda in 2014, establishing Function as a Service (FaaS) as the primary serverless compute model. This triggered widespread adoption across cloud platforms and established serverless as a distinct architectural approach.
Serverless architecture operates on event-driven execution. Functions execute in response to events—HTTP requests, database changes, file uploads, scheduled triggers, or message queue entries. The cloud provider handles deployment, scaling, load balancing, and infrastructure management. Functions run in isolated, stateless containers that spin up on demand and terminate after execution.
The billing model charges only for actual compute time measured in milliseconds, plus any associated resource usage. This contrasts with traditional infrastructure-as-a-service models that charge for allocated capacity regardless of utilization. A function that executes for 200ms once per hour incurs charges for those 200ms, not for the entire hour.
# AWS Lambda Ruby function structure
require 'json'
def lambda_handler(event:, context:)
# Function executes only when triggered
# No server management required
request_id = context.request_id
input_data = JSON.parse(event['body'])
result = process_data(input_data)
{
statusCode: 200,
body: JSON.generate(result)
}
end
def process_data(data)
# Business logic
{ processed: data['value'].upcase }
end
Serverless platforms provide automatic scaling that responds to demand in real time. A single function invocation runs in one container, while 10,000 simultaneous invocations spawn 10,000 containers. This eliminates capacity planning and handles traffic spikes without manual intervention.
The architecture introduces constraints that shape application design. Functions must be stateless—each invocation starts with no knowledge of previous executions. State persists in external services like databases, object storage, or caching layers. Execution time limits restrict long-running processes, typically ranging from seconds to 15 minutes depending on the platform.
Key Principles
Event-Driven Execution forms the foundation of serverless architecture. Functions remain dormant until events trigger execution. Event sources include HTTP endpoints, database streams, message queues, object storage notifications, scheduled timers, and custom application events. Each event carries a payload that provides context and data for the function.
The event-driven model decouples components through asynchronous communication. A file upload event triggers image processing without the upload endpoint waiting for completion. Multiple functions can respond to the same event independently, enabling parallel processing and fan-out patterns.
Stateless Computation requires functions to treat each invocation as independent. Functions cannot rely on in-memory state, local file systems, or connection pools persisting between invocations. The platform may reuse containers for subsequent invocations (warm starts) or create new containers (cold starts), making persistence unpredictable.
State management moves to external services. Databases store persistent data, distributed caches hold temporary state, object storage contains files, and message queues coordinate workflow state. Functions read required state at invocation start and write state changes before returning.
# Stateless function design
require 'aws-sdk-dynamodb'
def lambda_handler(event:, context:)
dynamodb = Aws::DynamoDB::Client.new
# Read state from external service
response = dynamodb.get_item(
table_name: 'UserSessions',
key: { 'user_id' => event['user_id'] }
)
session_data = response.item
# Process with retrieved state
updated_data = process_session(session_data, event['action'])
# Write state back to external service
dynamodb.put_item(
table_name: 'UserSessions',
item: updated_data
)
{ statusCode: 200 }
end
Automatic Scaling adjusts function instances based on incoming event volume. The platform monitors event rates and spawns additional containers when concurrent executions exceed available capacity. Scaling occurs without configuration, deployment, or manual intervention.
Scaling responds to traffic patterns in real time. A function handling 10 requests per second may run in 10 containers if each invocation takes one second. If traffic spikes to 1,000 requests per second, the platform provisions 1,000 containers. When traffic drops, containers terminate and scaling reverses.
Cold starts occur when the platform creates new containers. The provider must allocate resources, initialize the runtime environment, and load function code before execution begins. This adds latency to the first request, typically 100ms to several seconds depending on runtime, dependencies, and function size. Warm containers reuse existing environments and execute immediately.
Consumption-Based Pricing charges for resources used during execution rather than allocated capacity. Pricing factors include execution time measured in milliseconds, memory allocation, and number of invocations. Additional charges apply for associated services like data transfer, API gateway requests, and database operations.
Cost efficiency emerges from resource sharing and granular billing. A function executing 1 million times per month for 100ms each with 128MB memory costs approximately $0.20 on AWS Lambda (2024 pricing), while equivalent always-on compute might cost $10-50 per month. The gap widens for infrequently executed functions or highly variable workloads.
Managed Infrastructure transfers operational responsibilities to the cloud provider. The platform handles server provisioning, operating system updates, security patches, capacity planning, monitoring, and fault tolerance. Developers deploy code without managing underlying infrastructure.
This managed approach reduces operational complexity but increases platform dependency. The provider controls runtime versions, execution environments, and service limits. Applications must conform to platform constraints and adapt to provider changes.
Ephemeral Execution means functions exist only during invocation. Containers start when events arrive and terminate after execution completes or timeout elapses. The execution environment provides a temporary file system that disappears when the container terminates.
Ephemeral execution affects resource management. Database connections cannot persist across invocations reliably. File processing must use object storage rather than local disks. Background threads or processes terminate when the function returns, potentially causing data loss.
Design Considerations
Serverless architecture suits specific workload patterns while introducing trade-offs that affect design decisions. The model excels for event-driven, variable-traffic, or short-duration workloads but faces limitations with steady-state, long-running, or latency-sensitive operations.
Traffic Patterns determine serverless suitability. Variable or unpredictable traffic benefits from automatic scaling and pay-per-use pricing. An API handling 100 requests per hour with occasional spikes to 10,000 requests scales efficiently without over-provisioning. Consistent, predictable traffic may cost more in serverless than reserved capacity with traditional infrastructure.
Bursty workloads exploit serverless strengths. Batch processing triggered by file uploads, webhook receivers processing sporadic events, or scheduled maintenance tasks execute only when needed. Idle time incurs zero compute costs, making serverless economical for intermittent operations.
Execution Duration constraints limit serverless applicability. Most platforms impose timeout limits—AWS Lambda allows up to 15 minutes, Google Cloud Functions up to 60 minutes. Functions exceeding these limits must split work into smaller chunks or use traditional compute services.
Long-running workflows require orchestration patterns. AWS Step Functions, Azure Durable Functions, or custom state machines coordinate multiple function invocations to complete extended processes. Each step executes within timeout limits while maintaining workflow state externally.
# Breaking long work into smaller chunks
def lambda_handler(event:, context:)
sqs = Aws::SQS::Client.new
s3 = Aws::S3::Client.new
# Process batch of items
items = event['items'][0...100] # Process 100 items
remaining = event['items'][100..-1]
items.each do |item|
process_item(item)
end
# Queue next batch if work remains
if remaining && remaining.any?
sqs.send_message(
queue_url: ENV['QUEUE_URL'],
message_body: JSON.generate({ items: remaining })
)
end
{ processed: items.size }
end
Cold Start Latency affects user-facing applications. Initial invocations experience startup delays while the platform provisions containers and initializes runtimes. Ruby cold starts typically range from 200ms to 2 seconds depending on dependencies. Warm containers respond in single-digit milliseconds.
Cold start mitigation strategies include keeping functions warm with scheduled invocations, reducing deployment package size, minimizing dependencies, and using provisioned concurrency where available. Alternatively, design around cold starts by accepting occasional latency spikes or using serverless for non-critical paths.
State Management Complexity increases with stateless constraints. Traditional applications maintain state in memory, connection pools, or local caches. Serverless applications externalize state, adding network calls and coordination overhead.
State externalization patterns include storing session data in Redis or DynamoDB, caching computed values in CloudFront or API Gateway, maintaining workflow state in Step Functions or SQS, and keeping file processing state in S3 object metadata. Each pattern adds latency but enables horizontal scaling.
Vendor Lock-in concerns arise from platform-specific services and APIs. AWS Lambda functions integrate tightly with DynamoDB, S3, and other AWS services. Google Cloud Functions optimize for Google Cloud Storage and Firestore. Migrating between providers requires significant refactoring.
Lock-in mitigation strategies include abstracting platform APIs behind interfaces, using portable frameworks like Serverless Framework, containerizing functions with platform-agnostic runtimes, or accepting lock-in as a trade-off for platform benefits.
Cost Predictability varies by workload characteristics. Consistent traffic with known patterns produces predictable costs. Variable traffic, especially with unexpected spikes, creates cost uncertainty. Runaway functions triggered by malicious actors or bugs can generate substantial charges.
Cost control measures include setting budget alerts, implementing request throttling, using reserved capacity for baseline load, monitoring execution patterns, and testing thoroughly to prevent inefficient code from executing in production.
Implementation Approaches
Serverless architecture encompasses multiple implementation strategies, each addressing different use cases and operational requirements.
Function as a Service (FaaS) provides the core serverless compute model. Developers write individual functions triggered by events, deploy them to the platform, and allow the provider to manage execution. FaaS platforms include AWS Lambda, Google Cloud Functions, Azure Functions, and Cloudflare Workers.
FaaS implementations focus on single-purpose functions that execute specific tasks. An image resizing function, payment processor, or data validation routine each runs independently. Functions compose into larger applications through event chains and orchestration.
Function deployment involves packaging code and dependencies, configuring triggers and permissions, and uploading to the platform. Deployment automation through infrastructure-as-code tools manages configuration across environments.
# Ruby FaaS function with S3 trigger
require 'aws-sdk-s3'
require 'mini_magick'
def lambda_handler(event:, context:)
s3 = Aws::S3::Client.new
# Extract S3 event details
record = event['Records'].first
bucket = record['s3']['bucket']['name']
key = record['s3']['object']['key']
# Download image
image_data = s3.get_object(bucket: bucket, key: key).body.read
# Process image
image = MiniMagick::Image.read(image_data)
image.resize '200x200'
# Upload thumbnail
thumbnail_key = key.gsub(/(\.\w+)$/, '_thumb\1')
s3.put_object(
bucket: bucket,
key: thumbnail_key,
body: image.to_blob
)
{ statusCode: 200, thumbnail: thumbnail_key }
end
Backend as a Service (BaaS) combines serverless compute with managed backend services. BaaS platforms provide databases, authentication, file storage, and APIs without server management. Firebase, Supabase, and AWS Amplify exemplify BaaS approaches.
BaaS implementations integrate frontend applications directly with managed services, reducing or eliminating custom backend code. Client applications authenticate users through managed auth services, store data in managed databases, and trigger serverless functions for custom logic.
This approach suits mobile applications, single-page web apps, and rapid prototyping scenarios where reducing backend development time outweighs flexibility concerns.
Container-Based Serverless runs containerized applications in serverless environments. AWS Fargate, Google Cloud Run, and Azure Container Instances provide container execution without managing orchestration platforms. These services bridge traditional containerized applications and serverless operations.
Container-based serverless supports existing applications, languages, or frameworks incompatible with FaaS runtime constraints. Applications package in Docker containers with complete control over runtime environment, dependencies, and execution duration.
# Containerized Ruby serverless application
FROM ruby:3.2-slim
WORKDIR /app
COPY Gemfile* ./
RUN bundle install
COPY . .
# Must listen on PORT environment variable
CMD ["ruby", "app.rb"]
# app.rb - Sinatra app for Cloud Run
require 'sinatra'
require 'json'
set :bind, '0.0.0.0'
set :port, ENV['PORT'] || 8080
post '/process' do
content_type :json
data = JSON.parse(request.body.read)
result = perform_processing(data)
JSON.generate(result)
end
get '/health' do
'OK'
end
Event-Driven Orchestration coordinates multiple functions into complex workflows. AWS Step Functions, Azure Durable Functions, or custom orchestration with message queues manage state transitions, error handling, and retry logic across distributed function invocations.
Orchestration patterns include sequential workflows where functions execute in order, parallel processing where multiple functions run concurrently, conditional branching based on function results, and error handling with automatic retries and compensation logic.
# Step Functions state machine definition (Ruby SDK)
require 'aws-sdk-states'
states = Aws::States::Client.new
definition = {
Comment: 'Image processing workflow',
StartAt: 'ValidateImage',
States: {
ValidateImage: {
Type: 'Task',
Resource: 'arn:aws:lambda:region:account:function:validate',
Next: 'ProcessImage',
Catch: [{
ErrorEquals: ['ValidationError'],
Next: 'HandleError'
}]
},
ProcessImage: {
Type: 'Parallel',
Branches: [
{
StartAt: 'CreateThumbnail',
States: {
CreateThumbnail: {
Type: 'Task',
Resource: 'arn:aws:lambda:region:account:function:thumbnail',
End: true
}
}
},
{
StartAt: 'ExtractMetadata',
States: {
ExtractMetadata: {
Type: 'Task',
Resource: 'arn:aws:lambda:region:account:function:metadata',
End: true
}
}
}
],
Next: 'Complete'
},
Complete: {
Type: 'Succeed'
},
HandleError: {
Type: 'Fail'
}
}
}.to_json
states.create_state_machine(
name: 'ImageProcessingWorkflow',
definition: definition,
role_arn: 'arn:aws:iam::account:role/step-functions-role'
)
Hybrid Architectures combine serverless and traditional components. Core infrastructure runs on containers or VMs while serverless functions handle specific workloads like API endpoints, event processing, or scheduled tasks. This approach balances serverless benefits with traditional compute predictability.
Hybrid implementations position serverless at application edges for variable-traffic endpoints, background processing for asynchronous tasks, and integration points between systems. Core application logic may remain on traditional infrastructure for performance, cost, or architectural reasons.
Ruby Implementation
Ruby supports serverless deployment across major cloud platforms with native runtimes and framework support. AWS Lambda provides managed Ruby runtimes, while other platforms support Ruby through custom containers or buildpacks.
AWS Lambda Ruby Runtime offers official support for Ruby versions 2.7, 3.2, and 3.3. The runtime includes the Ruby interpreter, AWS SDK for Ruby, and access to AWS services through environment variables and IAM roles.
Lambda packages Ruby functions as zip files or container images. Zip deployment includes function code, Gemfile, and dependencies installed with bundle install --deployment. Container deployment provides complete control over Ruby version and system dependencies.
# lambda_function.rb - Entry point
require 'json'
require 'aws-sdk-dynamodb'
def lambda_handler(event:, context:)
# Context object provides execution metadata
puts "Request ID: #{context.request_id}"
puts "Function name: #{context.function_name}"
puts "Memory limit: #{context.memory_limit_in_mb}MB"
puts "Time remaining: #{context.get_remaining_time_in_millis}ms"
# Process event
body = JSON.parse(event['body']) if event['body']
dynamodb = Aws::DynamoDB::Client.new
result = dynamodb.put_item(
table_name: ENV['TABLE_NAME'],
item: {
'id' => SecureRandom.uuid,
'data' => body,
'timestamp' => Time.now.to_i
}
)
{
statusCode: 200,
headers: { 'Content-Type' => 'application/json' },
body: JSON.generate({ message: 'Success', id: result[:attributes]['id'] })
}
end
Jets Framework provides a Ruby-specific serverless framework modeled after Ruby on Rails. Jets applications deploy to AWS Lambda with API Gateway, enabling Rails-like development patterns in serverless environments.
Jets handles routing, controllers, models, and database migrations. The framework compiles Ruby code into Lambda functions, generates necessary AWS resources, and manages deployment lifecycle.
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
def index
posts = Post.all
render json: posts
end
def create
post = Post.create(post_params)
render json: post, status: :created
end
def show
post = Post.find(params[:id])
render json: post
end
private
def post_params
params.require(:post).permit(:title, :content)
end
end
# app/models/post.rb
class Post < ApplicationRecord
validates :title, presence: true
end
# config/routes.rb
Jets.application.routes.draw do
resources :posts
end
Serverless Framework with Ruby supports Ruby function deployment across multiple cloud providers. The framework uses YAML configuration to define functions, events, and resources, then deploys to AWS Lambda, Azure Functions, or Google Cloud Functions.
# serverless.yml
service: ruby-api
provider:
name: aws
runtime: ruby3.2
region: us-east-1
environment:
REDIS_URL: ${env:REDIS_URL}
functions:
processOrder:
handler: handlers/orders.process
events:
- sqs:
arn:
Fn::GetAtt:
- OrderQueue
- Arn
timeout: 30
memorySize: 256
apiEndpoint:
handler: handlers/api.handle
events:
- http:
path: /orders
method: post
cors: true
resources:
Resources:
OrderQueue:
Type: AWS::SQS::Queue
Properties:
QueueName: orders-queue
VisibilityTimeout: 60
# handlers/orders.rb
require 'json'
require 'redis'
def process(event:, context:)
redis = Redis.new(url: ENV['REDIS_URL'])
event['Records'].each do |record|
message = JSON.parse(record['body'])
# Process order
order_id = message['orderId']
process_order(order_id)
# Cache result
redis.setex("order:#{order_id}", 3600, 'processed')
end
{ statusCode: 200 }
end
def process_order(order_id)
# Order processing logic
sleep(0.5) # Simulate processing
end
Custom Container Deployment packages Ruby applications in Docker containers for platforms like Google Cloud Run or AWS Fargate. This approach supports any Ruby version, system dependencies, or framework without runtime constraints.
# Gemfile
source 'https://rubygems.org'
gem 'puma'
gem 'sinatra'
gem 'pg'
gem 'redis'
# app.rb
require 'sinatra'
require 'pg'
require 'redis'
require 'json'
configure do
set :bind, '0.0.0.0'
set :port, ENV.fetch('PORT', 8080)
$db = PG.connect(ENV['DATABASE_URL'])
$redis = Redis.new(url: ENV['REDIS_URL'])
end
post '/api/users' do
content_type :json
data = JSON.parse(request.body.read)
# Check cache
cached = $redis.get("user:#{data['email']}")
return cached if cached
# Create user
result = $db.exec_params(
'INSERT INTO users (email, name) VALUES ($1, $2) RETURNING id',
[data['email'], data['name']]
)
response = { id: result[0]['id'], email: data['email'] }
$redis.setex("user:#{data['email']}", 300, response.to_json)
JSON.generate(response)
end
Tools & Ecosystem
The serverless ecosystem includes cloud platforms, deployment frameworks, monitoring services, and development tools that support serverless application development and operations.
AWS Lambda dominates the serverless compute market with comprehensive service integration. Lambda supports Ruby 2.7, 3.2, and 3.3 runtimes with direct access to DynamoDB, S3, SQS, SNS, and other AWS services. Event sources include API Gateway for HTTP, EventBridge for scheduled events, SQS for message queues, S3 for object storage events, and DynamoDB Streams for database changes.
Lambda functions configure memory allocation from 128MB to 10GB, with CPU resources scaling proportionally. Execution timeout extends up to 15 minutes. Concurrent execution limits default to 1,000 with options to increase through service quotas.
Google Cloud Functions provides HTTP and event-driven functions with support for Ruby through custom buildpacks or container deployment. Cloud Run offers containerized serverless execution with support for any Ruby version or framework. Functions integrate with Cloud Storage, Cloud Pub/Sub, and Firestore.
Cloud Run excels for containerized Ruby applications requiring specific dependencies or long execution times. Functions execute up to 60 minutes with 32GB memory limits. Built-in load balancing and automatic HTTPS provisioning simplify deployment.
Azure Functions supports Ruby through custom handlers or container deployment. Functions integrate with Azure Storage, Event Grid, Service Bus, and Cosmos DB. The consumption plan provides serverless execution with per-second billing.
Serverless Framework offers provider-agnostic infrastructure-as-code for Ruby functions. The framework generates CloudFormation templates for AWS, ARM templates for Azure, or Deployment Manager configs for Google Cloud. Plugin ecosystem extends functionality for monitoring, deployment, and testing.
# Serverless Framework commands
serverless create --template aws-ruby --path my-service
cd my-service
# Deploy to AWS
serverless deploy --stage prod
# Invoke function
serverless invoke --function processOrder --data '{"orderId": "123"}'
# View logs
serverless logs --function processOrder --tail
# Remove service
serverless remove
AWS SAM (Serverless Application Model) provides CloudFormation extensions for serverless applications. SAM templates define Lambda functions, API Gateway endpoints, and DynamoDB tables with simplified syntax. Local testing simulates Lambda execution environments.
# template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Globals:
Function:
Runtime: ruby3.2
Timeout: 30
Environment:
Variables:
TABLE_NAME: !Ref OrdersTable
Resources:
OrderFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: src/
Handler: order_handler.lambda_handler
Events:
Api:
Type: Api
Properties:
Path: /orders
Method: post
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref OrdersTable
OrdersTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: orders
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
AWS CDK with Ruby enables infrastructure definition in Ruby code. The CDK synthesizes CloudFormation templates from Ruby classes, providing type safety and reusable constructs.
# lib/app-stack.rb
require 'aws-cdk-lib'
require 'aws-cdk-lib/aws-lambda'
require 'aws-cdk-lib/aws-apigateway'
class AppStack < Aws::Cdk::Stack
def initialize(scope, id, props = {})
super
# Define Lambda function
function = Aws::Lambda::Function.new(self, 'OrderHandler',
runtime: Aws::Lambda::Runtime::RUBY_3_2,
handler: 'handler.process',
code: Aws::Lambda::Code.from_asset('lambda'),
memory_size: 256,
timeout: Aws::Cdk::Duration.seconds(30)
)
# Create API Gateway
api = Aws::Apigateway::RestApi.new(self, 'OrderApi',
rest_api_name: 'Order Service'
)
orders = api.root.add_resource('orders')
orders.add_method('POST',
Aws::Apigateway::LambdaIntegration.new(function)
)
end
end
Monitoring and Observability tools track serverless application performance. AWS CloudWatch provides logs, metrics, and alarms. CloudWatch Insights queries logs for analysis. X-Ray traces distributed request flows across functions and services.
Third-party monitoring includes Datadog, New Relic, and Honeycomb with Ruby agent support. These services correlate logs, metrics, and traces for comprehensive observability.
# Ruby Lambda with AWS X-Ray tracing
require 'aws-xray-sdk'
require 'aws-sdk-dynamodb'
XRay.recorder.configure(
context: XRay::Context.new,
emitter: XRay::Emitter.new
)
def lambda_handler(event:, context:)
XRay.recorder.capture('process_order') do |subsegment|
subsegment.annotations[:order_id] = event['orderId']
dynamodb = Aws::DynamoDB::Client.new
XRay.recorder.capture('dynamodb_query') do
dynamodb.get_item(
table_name: 'Orders',
key: { 'id' => event['orderId'] }
)
end
end
{ statusCode: 200 }
end
Real-World Applications
Serverless architecture applies to diverse production scenarios where event-driven execution, automatic scaling, and operational simplicity provide value.
API Backends implement RESTful or GraphQL APIs with serverless functions behind API Gateway. Each endpoint maps to a dedicated function handling specific operations. This pattern suits APIs with variable traffic or microservice architectures.
# Product API implementation
require 'aws-sdk-dynamodb'
require 'json'
def list_products(event:, context:)
dynamodb = Aws::DynamoDB::Client.new
result = dynamodb.scan(
table_name: ENV['PRODUCTS_TABLE'],
limit: 50
)
products = result.items.map do |item|
{
id: item['id'],
name: item['name'],
price: item['price'].to_f,
stock: item['stock'].to_i
}
end
{
statusCode: 200,
headers: {
'Content-Type' => 'application/json',
'Access-Control-Allow-Origin' => '*'
},
body: JSON.generate({ products: products })
}
end
def get_product(event:, context:)
product_id = event['pathParameters']['id']
dynamodb = Aws::DynamoDB::Client.new
result = dynamodb.get_item(
table_name: ENV['PRODUCTS_TABLE'],
key: { 'id' => product_id }
)
return not_found unless result.item
{
statusCode: 200,
headers: { 'Content-Type' => 'application/json' },
body: JSON.generate(result.item)
}
end
def not_found
{
statusCode: 404,
body: JSON.generate({ error: 'Product not found' })
}
end
Data Processing Pipelines process large datasets through chains of serverless functions. S3 upload events trigger transformation functions, which write results that trigger downstream processing. This pattern handles batch ETL, log analysis, or data validation.
A production data pipeline might ingest CSV files into S3, trigger a validation function that checks data quality, spawn parallel processing functions for transformation, aggregate results in a database, and send completion notifications. Each stage scales independently based on data volume.
# CSV processing pipeline
require 'csv'
require 'aws-sdk-s3'
require 'aws-sdk-sqs'
def process_csv(event:, context:)
s3 = Aws::S3::Client.new
sqs = Aws::SQS::Client.new
bucket = event['Records'].first['s3']['bucket']['name']
key = event['Records'].first['s3']['object']['key']
# Stream CSV from S3
response = s3.get_object(bucket: bucket, key: key)
csv_data = response.body.read
# Parse and batch records
records = []
CSV.parse(csv_data, headers: true) do |row|
records << row.to_h
# Send batch of 100 to processing queue
if records.size >= 100
send_batch(sqs, records)
records = []
end
end
# Send remaining records
send_batch(sqs, records) if records.any?
{ statusCode: 200, processed: key }
end
def send_batch(sqs, records)
sqs.send_message(
queue_url: ENV['PROCESSING_QUEUE'],
message_body: JSON.generate({ records: records })
)
end
Webhook Handlers receive HTTP callbacks from external services. Payment processors, monitoring systems, or third-party APIs send event notifications to serverless endpoints. Functions validate signatures, process events, and trigger appropriate actions.
Production webhook handlers implement retry logic, idempotency checking, and secure signature verification. Functions often write events to durable queues for asynchronous processing, ensuring quick webhook responses while handling complex operations in background functions.
Scheduled Tasks execute maintenance operations, report generation, or data synchronization on defined schedules. CloudWatch Events or EventBridge triggers functions at specified intervals. This pattern replaces cron jobs with serverless execution.
# Scheduled cleanup task
require 'aws-sdk-s3'
def cleanup_old_files(event:, context:)
s3 = Aws::S3::Client.new
bucket = ENV['BUCKET_NAME']
cutoff_date = Time.now - (30 * 24 * 60 * 60) # 30 days ago
deleted_count = 0
# List and delete old objects
s3.list_objects_v2(bucket: bucket).each do |response|
response.contents.each do |object|
if object.last_modified < cutoff_date
s3.delete_object(bucket: bucket, key: object.key)
deleted_count += 1
end
end
end
puts "Deleted #{deleted_count} objects older than 30 days"
{ statusCode: 200, deleted: deleted_count }
end
Real-Time Stream Processing analyzes data streams from IoT devices, application logs, or user activity. Kinesis Data Streams or DynamoDB Streams trigger functions that aggregate metrics, detect anomalies, or update dashboards. Functions process records in micro-batches, enabling near-real-time analytics.
Image and Media Processing transforms uploaded media files. S3 upload events trigger functions that generate thumbnails, extract metadata, transcode videos, or apply filters. Parallel function invocations process multiple files simultaneously, scaling with upload volume.
Reference
Platform Comparison
| Platform | Ruby Support | Max Duration | Max Memory | Cold Start |
|---|---|---|---|---|
| AWS Lambda | Native 2.7, 3.2, 3.3 | 15 minutes | 10 GB | 200ms-2s |
| Google Cloud Functions | Custom runtime | 60 minutes | 32 GB | 500ms-3s |
| Google Cloud Run | Container | 60 minutes | 32 GB | 300ms-2s |
| Azure Functions | Custom handler | 10 minutes | 14 GB | 1s-3s |
| Cloudflare Workers | Not supported | 50ms-30s | 128 MB | <1ms |
Event Source Types
| Event Source | Description | Use Case | Lambda Integration |
|---|---|---|---|
| API Gateway | HTTP requests | REST APIs, webhooks | HTTP trigger |
| S3 | Object storage events | File processing, ETL | S3 event notification |
| DynamoDB Streams | Database changes | Change data capture | Stream trigger |
| SQS | Message queue | Asynchronous processing | Queue trigger |
| SNS | Pub/sub messaging | Fan-out notifications | Topic subscription |
| EventBridge | Scheduled or custom events | Cron jobs, event routing | Rule target |
| Kinesis | Data streaming | Real-time analytics | Stream trigger |
Cost Factors
| Factor | AWS Lambda | Google Cloud Functions | Azure Functions |
|---|---|---|---|
| Requests | $0.20 per 1M | $0.40 per 1M | $0.20 per 1M |
| Duration | $0.0000166667 per GB-second | $0.0000025 per GB-second | $0.000016 per GB-second |
| Free Tier | 1M requests, 400K GB-seconds | 2M requests, 400K GB-seconds | 1M requests, 400K GB-seconds |
Function Configuration
| Setting | Purpose | Typical Range | Consideration |
|---|---|---|---|
| Memory | RAM allocation | 128 MB - 10 GB | CPU scales with memory |
| Timeout | Max execution time | 1s - 900s | Affects cost and UX |
| Concurrency | Max parallel executions | 1 - 1000 | Prevents runaway costs |
| Reserved Concurrency | Dedicated capacity | 0 - 1000 | Reduces cold starts |
| Environment Variables | Configuration | N/A | Avoid secrets |
Ruby Lambda Response Format
| Field | Type | Required | Description |
|---|---|---|---|
| statusCode | Integer | Yes | HTTP status code |
| headers | Hash | No | Response headers |
| body | String | No | Response body as JSON string |
| isBase64Encoded | Boolean | No | Indicates binary response |
Common Patterns
| Pattern | Implementation | Benefit |
|---|---|---|
| Fan-out | SNS topic to multiple functions | Parallel processing |
| Queue-based | SQS queue with function consumer | Throttling, retry |
| Saga | Step Functions orchestration | Distributed transactions |
| CQRS | Separate read/write functions | Scalability |
| Event sourcing | DynamoDB Streams to functions | Audit trail |
Deployment Checklist
| Task | Tool | Purpose |
|---|---|---|
| Package dependencies | bundle install | Include gems |
| Configure IAM roles | AWS IAM | Grant permissions |
| Set environment variables | Provider config | Runtime configuration |
| Define event sources | Infrastructure as code | Trigger configuration |
| Configure monitoring | CloudWatch/X-Ray | Observability |
| Set alarms | CloudWatch Alarms | Error notification |
| Test locally | SAM CLI or Docker | Validate before deploy |
| Deploy | Serverless Framework/SAM | Push to production |