Alright, let’s talk about the knobs and dials you get to play with on your Lambda function. This isn’t just a boring configuration page; this is where you turn a generic piece of code into a tailored, efficient, and cost-effective component of your system. Get these wrong, and you’ll either be overpaying, underperforming, or waking up at 3 AM. No pressure.

Memory: The CPU Piggy Bank

Here’s the first thing AWS doesn’t scream from the rooftops: when you configure memory, you’re also configuring CPU. It’s a two-for-one deal, but they only advertise the memory part. AWS allocates CPU power linearly in proportion to the amount of memory you choose. Choose 128 MB? You get a sliver of a vCPU. Choose 1792 MB? You’re almost at a full vCPU (which is actually 1 vCPU at 1769 MB, but who’s counting).

Why should you care? Because if your function is CPU-bound—like processing an image, running an encryption algorithm, or crunching numbers—throwing more memory at it is literally how you make it run faster. A function that does a lot of waiting on network calls (IO-bound) won’t benefit as much.

The sweet spot? It’s different for every workload. You must test and use the Power Tuning tool to find the optimal setting for cost and performance. Running a function with too little memory is a fantastic way to discover the horror of out-of-memory errors, which usually just kill your invocation without a useful log message. Good luck debugging that.

# In your SAM template.yaml
Resources:
  MyOptimizedFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: function/
      Handler: app.lambda_handler
      Runtime: python3.9
      MemorySize: 1024 # 1024 MB also gets you a proportional CPU boost
      Timeout: 10

Timeout: Your Get-Out-of-Jail-Free Card

The timeout is your function’s personal life coach. It says, “You’ve had enough time, now stop.” The default is a horrifyingly long 3 seconds, which is an eternity in Lambda time. Always, and I mean always, set this explicitly. The maximum is 15 minutes (900 seconds), which is basically a lifetime for a short-lived compute service.

The reason this setting is so critical is that it’s your primary defense against runaway costs from a function stuck in a retry loop or waiting on a downstream service that died. Without it, a single misbehaving function could rack up a surprising bill.

Set it to a reasonable value for your use case. An API backend should probably timeout after 5-10 seconds. A data processing job might need the full 15 minutes. The key is to set it just above your function’s expected maximum duration, with a healthy safety margin. Don’t give it 15 minutes if it usually finishes in 2 seconds.

Environment Variables: Not for Secrets

Environment variables are fantastic for moving configuration out of your code. Database connection strings, feature flags, the URL of an external API—this is where they belong.

But here’s the massive, glaring, “how did this ever get past design” caveat: They are not secure by default. If you plain-text an API key into an environment variable, anyone with the lambda:GetFunctionConfiguration permission can see it. This is, frankly, a terrible default.

The correct way to handle secrets is to use AWS Secrets Manager or SSM Parameter Store (with the SecureString type). You then reference the ARN of the secret in your environment variable and use the SDK to fetch it within your function at runtime. It adds a bit of latency and cost, but it doesn’t leak your credentials to every intern with AWS CLI access.

import os
import boto3
from botocore.exceptions import ClientError

def get_secret():
    secret_name = os.environ['DB_SECRET_ARN']
    client = boto3.client('secretsmanager')

    try:
        response = client.get_secret_value(SecretId=secret_name)
    except ClientError as e:
        # Handle error appropriately
        raise e
    else:
        return response['SecretString']

# Use the secret
database_password = get_secret()

Tags: Your Future Self’s Best Friend

Tags are often dismissed as bureaucratic nonsense, but I beg to differ. They are how you tame the chaos of having hundreds of Lambda functions. When you get that dreaded email from finance asking, “Can you tell us what the $3,000 Lambda spend for ‘project-bamboo-v2-prod-us-east-1-analytics-layer-processor’ is for?”, tags are your answer.

Tag everything meaningfully. At a minimum, use:

  • project: The name of the project.
  • environment: dev, staging, prod.
  • owner: The team or individual responsible.

You can then use Cost Explorer to slice your bill by these tags. It’s the difference between a 10-minute answer and a 10-hour forensic accounting session.

# Tagging a function via AWS CLI
aws lambda tag-resource \
    --resource arn:aws:lambda:us-east-1:123456789012:function:my-function \
    --tags "project=project-bamboo,environment=prod,owner=backend-team"

Think of configuration not as a list of settings to gloss over, but as the primary way you shape your function’s behavior, cost, and resilience. It’s the difference between code that just runs and a function that runs well.