CrackedRuby CrackedRuby

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