Skip to content
>GLB_
Go back

Triggering AWS Glue Jobs from EventBridge: Workflows, Scheduler, and the IAM You Actually Need

Most tutorials skip a detail: an AWS Glue job is not a native target for an EventBridge rule. If you open the target dropdown, you’ll find Glue workflow, not Glue job.

So “trigger a Glue job from EventBridge” really means one of three patterns. Each has different IAM, different semantics, and different failure modes.

PatternUse whenEventBridge role needs
Rule → Glue workflow (EVENT trigger)Event-driven (S3 object created, custom events)glue:notifyEvent
EventBridge Scheduler → startJobRunTime-based (cron/rate)glue:StartJobRun
Rule → Step Functions → GlueYou need retries, waiting, chaining, notificationsstates:StartExecution

Pattern 1: EventBridge rule → Glue workflow

The workflow’s starting trigger must be of type EVENT. The job runs as an action of that trigger.

$ aws glue create-workflow --name ingest-events-wf

$ aws glue create-trigger \
    --name ingest-events-start \
    --workflow-name ingest-events-wf \
    --type EVENT \
    --event-batching-condition BatchSize=1,BatchWindow=900 \
    --actions JobName=ingest-events

BatchSize=1 starts the workflow on every event. Increase it to batch multiple S3 uploads into a single run. The workflow starts when either BatchSize events arrive or BatchWindow seconds pass.

If the job uses bookmarks, be careful with BatchSize=1 and MaxConcurrentRuns > 1: a burst of uploads can start overlapping runs that read the same bookmark state. See Debugging AWS Glue Job Bookmarks Not Working as Expected.

For S3 events, the bucket must send notifications to EventBridge. This is off by default:

$ aws s3api put-bucket-notification-configuration \
    --bucket my-raw-bucket \
    --notification-configuration '{"EventBridgeConfiguration": {}}'

The rule:

{
  "source": ["aws.s3"],
  "detail-type": ["Object Created"],
  "detail": {
    "bucket": { "name": ["my-raw-bucket"] },
    "object": { "key": [{ "prefix": "events/" }] }
  }
}

IAM for pattern 1

The target needs a role EventBridge can assume. Trust policy:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": { "Service": "events.amazonaws.com" },
    "Action": "sts:AssumeRole"
  }]
}

Permissions policy: glue:notifyEvent, not glue:StartJobRun. This is the most common mistake.

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "glue:notifyEvent",
    "Resource": "arn:aws:glue:us-east-1:123456789012:workflow/ingest-events-wf"
  }]
}

Attach the target:

$ aws events put-targets --rule s3-events-to-glue --targets \
    'Id=glue-wf,Arn=arn:aws:glue:us-east-1:123456789012:workflow/ingest-events-wf,RoleArn=arn:aws:iam::123456789012:role/eb-to-glue-wf'

The job itself still runs with its own Glue job role. EventBridge’s role only needs permission to notify the workflow.

To check whether the triggered run actually succeeded, see How to Get the Status of an AWS Glue Workflow Using boto3.

Pattern 2: EventBridge Scheduler → startJobRun

For time-based runs, EventBridge Scheduler supports universal targets: it can call almost any AWS API directly. No Lambda, no workflow.

$ aws scheduler create-schedule \
    --name nightly-ingest \
    --schedule-expression "cron(0 3 * * ? *)" \
    --schedule-expression-timezone "America/Argentina/Buenos_Aires" \
    --flexible-time-window Mode=OFF \
    --target '{
      "Arn": "arn:aws:scheduler:::aws-sdk:glue:startJobRun",
      "RoleArn": "arn:aws:iam::123456789012:role/scheduler-to-glue",
      "Input": "{\"JobName\": \"ingest-events\", \"Arguments\": {\"--run_mode\": \"nightly\"}}"
    }'

Input is the request body of the StartJobRun API, so you can pass job arguments directly.

IAM for pattern 2

Trust scheduler.amazonaws.com:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": { "Service": "scheduler.amazonaws.com" },
    "Action": "sts:AssumeRole"
  }]
}

Permissions:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "glue:StartJobRun",
    "Resource": "arn:aws:glue:us-east-1:123456789012:job/ingest-events"
  }]
}

If you only need a schedule, a native Glue SCHEDULED trigger also works. Scheduler wins when you want time zones, one-off schedules, or a single place for all schedules across services.

Pattern 3: Rule → Step Functions → Glue

When you need more than “start the job” (wait for completion, retry on failure, notify on error, chain a crawler), put Step Functions in between. The .sync integration waits for the job to finish:

{
  "StartAt": "RunGlueJob",
  "States": {
    "RunGlueJob": {
      "Type": "Task",
      "Resource": "arn:aws:states:::glue:startJobRun.sync",
      "Parameters": { "JobName": "ingest-events" },
      "Retry": [{
        "ErrorEquals": ["States.ALL"],
        "MaxAttempts": 2,
        "BackoffRate": 2
      }],
      "End": true
    }
  }
}

IAM for pattern 3

Two roles:

Missing glue:GetJobRun is a classic: the job starts, then the execution fails because Step Functions can’t poll the status.

Debugging checklist

References


Share this post:

Related Posts


Previous Post
COALESCE doesn't care what your columns mean
Next Post
Debugging AWS Glue Job Bookmarks Not Working as Expected