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
| Attribute | event | context |
|---|---|---|
| Definition | Invocation payload supplied by the trigger | Runtime metadata supplied by the Lambda service |
| Variability | Structure varies by invocation source | Consistent structure across invocations |
| Data type in Python | dict | Object with attributes |
| Access pattern | event["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.
- Navigate to Lambda > Create function > Author from scratch > Python 3.12 > Function name
event-context-lab - 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})
}- Select Test > Create test event with the following payload:
1
2
3
4
{
"emoji_type": 1,
"message": "hello from console"
}- 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: " + messageThis 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:
context.aws_request_id- Unique identifier for the invocation. Used for log correlation.context.log_group_nameandcontext.log_stream_name- CloudWatch Logs destination. Format:/aws/lambda/function-namecontext.get_remaining_time_in_millis()- Remaining execution time before timeout. Used to terminate processing proactively.
Additional attributes:
context.function_name- Configured function namecontext.function_version- Published version or$LATESTcontext.invoked_function_arn- Full ARN, including alias where applicablecontext.memory_limit_in_mb- Configured memory allocation
Implementation notes:
- Incorrect:
context["function_name"]- context is not subscriptable - Incorrect:
context.functionName- Python usesfunction_name. The camelCase variant applies to Node.js. - Incorrect:
context.get_remaining_time_in_milliswithout 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_idandget_remaining_time_in_millis()for observability and timeout management. - Event access uses dictionary syntax
[]. Context access uses attribute syntax. - API Gateway
bodyrequiresjson.loads. S3 object keys requireurllib.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.Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article