AWS Builder Center

AWS Lambda Invocation Model: Distinguishing Event and Context Objects in Python

An examination of AWS Lambda handler inputs based on console invocations. This article defines payload variability across triggers and runtime context attributes, with reproducible Python examples and CloudWatch Logs verification.

AWS Lambda Invocation Model: Distinguishing Event and Context Objects in Python

Category: Serverless | Level: Beginner | Reading time: 8 minutes
All Python functions on AWS Lambda share the same entry point:
1
def lambda_handler(event, context):
During initial development, the distinction between these two parameters is frequently overlooked until an invocation returns None via API Gateway while succeeding in the Lambda console. This article documents that behavior and defines the correct handling for each parameter.

Invocation Overview

Attributeeventcontext
DefinitionInvocation payload supplied by the triggerRuntime metadata supplied by the Lambda service
VariabilityStructure varies by invocation sourceConsistent structure across invocations
Data type in PythondictObject with attributes
Access patternevent["emoji_type"]context.function_name
Example content{"emoji_type": 1, "message": "hello"}function_name, aws_request_id, memory_limit_in_mb
Conceptual model: event contains the data to be processed. Context describes the environment in which processing occurs, including identifiers, limits, and remaining execution time.

Handler Implementation

The following implementation logs both parameters for verification in CloudWatch Logs.
Prerequisites: AWS Console access. No CLI configuration is required.
  1. Navigate to Lambda > Create function > Author from scratch > Python 3.12 > Function name event-context-lab
  2. Replace the default code with the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import json

def lambda_handler(event, context):
print("EVENT: " + json.dumps(event, indent=2))
print("Request ID:", context.aws_request_id)
print("Function:", context.function_name)
print("Version:", context.function_version)
print("Remaining ms:", context.get_remaining_time_in_millis())
print("Memory limit MB:", context.memory_limit_in_mb)
print("Log group:", context.log_group_name)

return {
"statusCode": 200,
"body": json.dumps({"ok": True})
}
  1. Select Test > Create test event with the following payload:
1
2
3
4
{
"emoji_type": 1,
"message": "hello from console"
}
  1. Execute the test, then review Monitor > Logs > CloudWatch Logs. The event is recorded as the submitted JSON. Context values including Request ID and remaining execution time are recorded alongside.
Standard verification procedure: log the event object prior to implementing extraction logic.
Reference implementation using a controlled payload:
1
2
3
4
5
6
7
8
9
emoji_type = event["emoji_type"]
message = event["message"]

if emoji_type == 0:
custom_message = "Message for code 0: " + message
elif emoji_type == 1:
custom_message = "Message for code 1: " + message
else:
custom_message = "Message for all other codes: " + message
This implementation is valid exclusively for this payload structure. Invocation by an AWS service requires adaptation to the corresponding event schema.

Event Structure by Invocation Source

No unified event schema exists. The structure is determined by the invoking service.
1. Direct invocation / console test
The payload is defined by the invoker:
1
2
3
4
{
"emoji_type": 1,
"message": "hello"
}
1
emoji_type = event["emoji_type"]
2. API Gateway proxy integration
API Gateway provides the full HTTP request context:
1
2
3
4
5
6
7
{
"httpMethod": "GET",
"path": "/my/path",
"queryStringParameters": {"type": "1"},
"body": "{\"emoji_type\": 1, \"message\": \"hello\"}",
"isBase64Encoded": false
}
1
2
3
4
import json
# body is transmitted as a string and requires deserialization
data = json.loads(event["body"])
emoji_type = data["emoji_type"]
Responses to API Gateway require proxy integration format. An incorrectly formatted response results in HTTP 502:
1
2
3
4
5
return {
"statusCode": 200,
"headers": {"Content-Type": "application/json"},
"body": json.dumps({"custom_message": custom_message})
}
3. Amazon S3 ObjectCreated notification
S3 delivers notifications in a Records array:
1
2
3
4
5
6
7
8
9
10
11
{
"Records": [
{
"eventSource": "aws:s3",
"s3": {
"bucket": {"name": "my-bucket"},
"object": {"key": "uploads/photo.jpg"}
}
}
]
}
1
2
3
import urllib.parse
bucket = event['Records'][0]['s3']['bucket']['name']
key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'])
Recommendation: inspect print(event) output in CloudWatch Logs before implementing field extraction.

Context Object Attributes

The context object maintains a consistent interface. Attributes relevant to routine development:
  1. context.aws_request_id - Unique identifier for the invocation. Used for log correlation.
  2. context.log_group_name and context.log_stream_name - CloudWatch Logs destination. Format: /aws/lambda/function-name
  3. context.get_remaining_time_in_millis() - Remaining execution time before timeout. Used to terminate processing proactively.
Additional attributes:
  • context.function_name - Configured function name
  • context.function_version - Published version or $LATEST
  • context.invoked_function_arn - Full ARN, including alias where applicable
  • context.memory_limit_in_mb - Configured memory allocation
Implementation notes:
  • Incorrect: context["function_name"] - context is not subscriptable
  • Incorrect: context.functionName - Python uses function_name. The camelCase variant applies to Node.js.
  • Incorrect: context.get_remaining_time_in_millis without parentheses - this member is a method and requires invocation
1
2
request_id = context.aws_request_id
remaining = context.get_remaining_time_in_millis()
Full specification: https://docs.aws.amazon.com/lambda/latest/dg/python-context.html and https://docs.aws.amazon.com/lambda/latest/dg/python-handler.html

Common Implementation Issues

Issue 1: Successful console test, null value via API Gateway
Console test:
1
event.get("type") # Returns value when test JSON contains "type"
API Gateway invocations do not contain type at the top level. Parameters reside in queryStringParameters and body. Consequently, event.get("type") evaluates to None.
Resolution:
1
2
3
4
5
6
import json
if event.get("body"):
data = json.loads(event["body"])
else:
data = event
value = data.get("type")
Issue 2: Missing positional argument during local evaluation
Direct invocation as lambda_handler(my_event) produces:
1
TypeError: lambda_handler() missing 1 required positional argument: 'context'
Lambda provides both arguments during managed execution. For local evaluation, supply a test object:
1
2
3
4
5
6
7
class FakeContext:
function_name = "local"
aws_request_id = "local-123"
def get_remaining_time_in_millis(self):
return 10000

lambda_handler({"emoji_type": 1, "message": "hi"}, FakeContext())

Key Observations

  • The event object contains invocation data and varies by trigger. Log the event with print(json.dumps(event)) prior to processing.
  • The context object contains runtime metadata with consistent structure. Utilize aws_request_id and get_remaining_time_in_millis() for observability and timeout management.
  • Event access uses dictionary syntax []. Context access uses attribute syntax .
  • API Gateway body requires json.loads. S3 object keys require urllib.parse.unquote_plus.
  • Handler signature is def lambda_handler(event, context): with two parameters.

Subsequent Areas of Study

  • Amazon API Gateway - HTTP exposure and proxy integration configuration
  • Amazon CloudWatch Logs - filtering by Request ID and retention management
  • Amazon DynamoDB - persistence of invocation results
Reference documentation:
  • https://docs.aws.amazon.com/lambda/latest/dg/python-programming-model.html
  • https://docs.aws.amazon.com/lambda/latest/dg/python-handler.html
  • https://docs.aws.amazon.com/lambda/latest/dg/python-context.html
  • https://docs.aws.amazon.com/lambda/latest/dg/services-apigateway.html
Discussion: indicate the invocation source utilized and the corresponding get_remaining_time_in_millis() value observed during execution. Additional observations regarding event schema variations are welcome in the comments.

Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article