Event-Driven AWS Glue Crawlers: Setting Up SQS-Based Triggers
Glue Crawlers can crawl based on S3 event notifications, avoiding a full scan and offering benefits in terms of both crawling performance and costs.
Glue Crawlers can crawl based on S3 event notifications, avoiding a full scan and offering benefits in terms of both crawling performance and costs.

Building
The CloudFormation template below sets up the queue, bucket, and crawler:
AWSTemplateFormatVersion: '2010-09-09'Description: Glue crawler test
Resources: SqsQueue: Type: AWS::SQS::Queue Properties: SqsManagedSseEnabled: true QueueName: glue-crawler-test-queue
SqsQueuePolicy: Type: AWS::SQS::QueuePolicy Properties: Queues: - !Ref SqsQueue PolicyDocument: Version: '2008-10-17' Id: __default_policy_ID Statement: - Effect: Allow Principal: AWS: - !Sub arn:aws:iam::${AWS::AccountId}:root - !GetAtt IAMRoleGlueCrawler.Arn Action: sqs:* Resource: !GetAtt SqsQueue.Arn - Effect: Allow Principal: Service: s3.amazonaws.com Action: sqs:* Resource: !GetAtt SqsQueue.Arn
S3Bucket: Type: AWS::S3::Bucket DependsOn: SqsQueuePolicy Properties: BucketName: !Sub glue-crawler-test-${AWS::AccountId}-${AWS::Region} BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: AES256 NotificationConfiguration: QueueConfigurations: - Event: 's3:ObjectCreated:*' Queue: !GetAtt SqsQueue.Arn PublicAccessBlockConfiguration: BlockPublicAcls: TRUE BlockPublicPolicy: TRUE IgnorePublicAcls: TRUE RestrictPublicBuckets: TRUE
IAMRoleGlueCrawler: Type: AWS::IAM::Role Properties: Path: /service-role/ RoleName: !Sub glue-crawler-test-service-role AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: glue.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: cw-logs PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: "*" - PolicyName: glue PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - glue:CreateTable - glue:GetDatabase - glue:GetTable - glue:UpdateTable Resource: "*" - PolicyName: s3 PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - s3:GetObject - s3:ListBucket - s3:PutObject Resource: '*'
GlueDatabase: Type: AWS::Glue::Database Properties: CatalogId: !Ref AWS::AccountId DatabaseInput: Name: glue-crawler-test-db
GlueTable: Type: AWS::Glue::Table Properties: CatalogId: !Ref AWS::AccountId DatabaseName: !Ref GlueDatabase TableInput: Name: glue-crawler-test-table TableType: EXTERNAL_TABLE Parameters: classification: json StorageDescriptor: Location: !Sub 's3://${S3Bucket}/' Compressed: false InputFormat: org.apache.hadoop.mapred.TextInputFormat OutputFormat: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat SerdeInfo: SerializationLibrary: org.openx.data.jsonserde.JsonSerDe
GlueCrawler: Type: AWS::Glue::Crawler Properties: Name: glue-crawler-test Role: !Sub service-role/${IAMRoleGlueCrawler} Targets: CatalogTargets: - DatabaseName: !Ref GlueDatabase Tables: - !Ref GlueTable SchemaChangePolicy: UpdateBehavior: UPDATE_IN_DATABASE DeleteBehavior: LOGDeploy the stack:
STACK_NAME=glue-crawler-test
aws cloudformation package \ --template-file template.yaml \ --s3-bucket <YOUR_CFN_BUCKET> \ --s3-prefix "$STACK_NAME/$(date +%Y)/$(date +%m)/$(date +%d)/$(date +%H)/$(date +%M)" \ --output-template-file package.template
aws cloudformation deploy \ --stack-name $STACK_NAME \ --template-file package.template \ --capabilities CAPABILITY_NAMED_IAMUpdating Glue Crawler Target Table Setting
CloudFormation does not currently support S3 event notifications for Glue Crawlers. Update the target table settings manually:
https://github.com/aws-cloudformation/cloudformation-coverage-roadmap/issues/947
CloudFormation Support For S3 Event isn’t currently available. S3 Event Crawler’s integration with CloudFormation is in scope and in the works. We plan on releasing this coverage to Cloudformation some later this year. Thank you for patience.
Select the table and click Edit.

Choose Crawl based on events in the Subsequent crawler runs section.

Testing
Feeding Version 1
Upload a sample JSON file to trigger an S3 event notification:
echo '{"message": "Hello World"}' > sample1.jsonaws s3 cp sample1.json s3://glue-crawler-test-<ACCOUNT_ID>-<REGION>/Start the Glue crawler:
aws glue start-crawler --name glue-crawler-testMonitor its status until it shows STOPPING:
$ aws glue get-crawler --name glue-crawler-test | jq -r '.Crawler.State'STOPPINGVerify the updated Glue table schema:
aws glue get-table \ --database-name glue-crawler-test-db \ --name glue-crawler-test-table \| jq '.Table.StorageDescriptor.Columns'Expected output:
[ { "Name": "message", "Type": "string" }]Feeding Version 2
Repeat the process with a new JSON file version:
echo '{"message": "Hello World", "statusCode": 200}' > sample2.jsonaws s3 cp sample2.json s3://glue-crawler-test-<ACCOUNT_ID>-<REGION>/Start the Glue crawler:
aws glue start-crawler --name glue-crawler-testMonitor its status until it shows STOPPING:
$ aws glue get-crawler --name glue-crawler-test | jq -r '.Crawler.State'STOPPINGVerify the updated Glue table schema:
aws glue get-table \ --database-name glue-crawler-test-db \ --name glue-crawler-test-table \| jq '.Table.StorageDescriptor.Columns'Expected output:
[ { "Name": "message", "Type": "string" }, { "Name": "statuscode", "Type": "int" }]Checking SQS Message Count
Verify that no messages are left in the SQS queue:
queue_url=$(aws sqs get-queue-url --queue-name glue-crawler-test-queue | jq -r '.QueueUrl')aws sqs get-queue-attributes \ --queue-url $queue_url \ --attribute-names ApproximateNumberOfMessages{ "Attributes": { "ApproximateNumberOfMessages": "0" }}Cleaning Up
Remove the resources provisioned by this example with:
aws s3 rm s3://glue-crawler-test-<ACCOUNT_ID>-<REGION>/ --recursiveaws cloudformation delete-stack --stack-name $STACK_NAMEConclusion
Wiring S3 event notifications through SQS into a Glue Crawler let two successive file uploads update the table schema incrementally, confirmed by an empty SQS queue afterward. That empty queue check at the end confirms the real benefit here: once event-based crawling is enabled, the crawler only processes the objects that triggered a notification rather than rescanning the whole bucket, which is what keeps both runtime and cost down as the dataset grows. The one step that can’t be automated yet is switching Subsequent crawler runs to Crawl based on events in the console, since CloudFormation doesn’t support that setting — worth tracking the linked GitHub issue if managing this entirely as code matters for a given project.
Related posts
Sign in with Slack Using Cognito User Pools and OIDC
Federating Cognito user pools with Slack over OIDC and wiring "Sign in with Slack" into a Next.js app with Amplify.
Deploying FastAPI on AWS Lambda with Lambda Web Adapter
This example guides you through the process of developing API backends with FastAPI using Lambda Web Adapter.
API Gateway WebSocket: Implementing a Mock Integration
Building an API Gateway WebSocket API entirely with mock integrations, returning canned responses with no backend Lambda involved.
Uploading to S3 Through CloudFront Pre-Signed URLs
CloudFront signed URLs let you upload to S3 through a custom domain—useful when direct S3 pre-signed URLs are not an option.
AWS EventBridge Scheduler: Starting and Stopping EC2 on a Schedule
Starting and stopping EC2 instances on a cron schedule with EventBridge Scheduler calling the EC2 API directly, no Lambda involved.
