How to Set Up AWS Glue: 12 Steps, 90 Min [2026]

AWS Glue is Amazon’s serverless data integration service, and by August 2026 its engine has moved twice in twelve months: AWS Glue 5.0 shipped on Apache Spark 3.5.4 in late 2024, and AWS Glue 5.1 followed on November 26, 2025 with Apache Spark 3.5.6, Python 3.11, and Scala 2.12.18. If you’re still running Glue 4.0 jobs or have never touched Glue at all, this tutorial gets you from zero to a working, scheduled ETL pipeline in 12 steps and about 90 minutes, using the current 5.1 runtime the whole way through.

By the end you’ll have a complete working project: an S3 data lake crawled into the Glue Data Catalog, a Spark ETL job that transforms raw CSV into partitioned Parquet, a Data Catalog you can query straight from Athena, and a schedule that runs it all automatically. We’ll also cover exactly what it costs in DPU-hours, the pitfalls that burn a surprising amount of first-week budget, and troubleshooting for the errors you’re most likely to hit along the way.

Google · Preferred Sources

Don't miss new tech stories on Google

Add Tech Insider once in the Google app and our stories appear in your news suggestions.

Add Now

What Is AWS Glue and Why It Matters in 2026

AWS Glue is a serverless data integration service built around three pieces: the Glue Data Catalog (a shared metadata store), Glue Crawlers (automated schema discovery), and Glue Jobs (the actual ETL compute, mostly running Apache Spark). Instead of standing up and patching a Spark cluster yourself, you point Glue at your data, let it infer the schema, write a transformation script, and Glue runs it on managed infrastructure billed by the second. The Data Catalog it builds isn’t Glue-only either — Athena, Redshift Spectrum, EMR, and Lake Formation all read from the same catalog, so cataloging your data once with Glue pays off across the rest of the AWS analytics stack.

What changed with the move to Glue 5.0 and then 5.1 is meaningful for anyone still on 4.0. According to AWS’s own Glue 5.0 announcement, the 5.0 runtime jumped from Spark 3.3.0 to Spark 3.5.4, alongside Python 3.11, Scala 2.12.18, and Java 17, plus updated open table format support: Hudi 0.15.0, Iceberg 1.7.1, and Delta Lake 3.3.0. Glue 5.0 also added support for Amazon SageMaker Unified Studio and SageMaker Lakehouse. Glue 5.1 followed with a further Spark bump to 3.5.6, described in AWS’s Glue 5.1 announcement as bringing performance and security enhancements on top of the same Python and Scala versions. Separately, a June 2025 AWS update added support for Glue 5.0 Spark jobs to read and write directly against AWS Lake Formation-registered tables, provided the job’s IAM role has full table access — a meaningful change for teams running lakehouse architectures with fine-grained access control.

None of that changes how you build a Glue pipeline day to day, which is what the rest of this tutorial walks through. But if you’re deciding which Glue version to target for a new project, there’s no reason to start on anything older than 5.1. The full version matrix, including the exact Hadoop, Iceberg, Hudi, and Delta Lake versions bundled with each Glue release, is maintained in AWS’s Glue versions release notes, worth bookmarking before you pin a version in a production job.

Where Glue Fits in a Real Data Platform

In practice, teams reach for Glue for a fairly consistent set of jobs: turning a messy S3 data lake of raw CSVs or JSON logs into a clean, partitioned, queryable table; syncing data out of an operational database like Amazon RDS into a data warehouse without hand-rolling extraction code; running scheduled batch transformations that feed a BI dashboard or a machine learning feature store; and increasingly, preparing data for the lakehouse pattern with Iceberg or Delta Lake tables shared across Glue, Athena, and Redshift Spectrum. If your workload looks like any of those and doesn’t need a persistent, always-on cluster, Glue’s serverless, pay-per-DPU-hour model is usually cheaper and less operational overhead than standing up and babysitting a dedicated Spark or EMR cluster sized for peak load it hits only occasionally.

Prerequisites: Tools, Accounts, and Versions You Need

Glue is entirely serverless, so there’s nothing to install to run it — everything runs on AWS-managed infrastructure. You do need a small set of local tools to script and deploy it, plus an S3 bucket to hold the sample data.

Tool or resourceVersion / tierInstall / setupWhy you need it
AWS accountFree tier or pay-as-you-goSign up at aws.amazon.comHosts every Glue resource in this tutorial
AWS CLILatest version (v2)curl “https://awscli.amazonaws.com/AWSCLIV2.pkg” -o AWSCLIV2.pkgCreates databases, crawlers, and jobs from the terminal
Python3.11 (matches Glue 5.1’s runtime)Download from python.org or use pyenvWriting and locally linting Glue ETL scripts
boto3Latest versionpip install boto3Scripting Glue API calls directly from Python
An S3 bucketN/Aaws s3 mb s3://your-bucket-nameStores raw data, scripts, and job output
An IAM role for GlueN/AAttach the AWSGlueServiceRole managed policyLets Glue jobs and crawlers read/write your resources

This tutorial writes Glue ETL scripts in Python, which is the most common path into Glue, but the same Spark jobs run equally well written in Scala if that’s what your team standardizes on. Everything else — the Data Catalog, crawlers, scheduling, IAM — is identical regardless of the scripting language you pick. If your workload is lightweight orchestration or scripting rather than a Spark transformation, Glue’s Python Shell job type is also worth knowing about: it runs plain Python without spinning up a Spark cluster at all, which is cheaper and faster to start for tasks that don’t need distributed processing.

Step 1: Create an S3 Bucket and Upload Sample Data

Glue needs raw data to work with. Create a bucket with a folder structure that separates raw input from Glue’s own script storage and the transformed output the ETL job will produce.

aws s3 mb s3://glue-tutorial-2026

# Folder layout Glue will read from and write to
aws s3api put-object --bucket glue-tutorial-2026 --key raw/
aws s3api put-object --bucket glue-tutorial-2026 --key scripts/
aws s3api put-object --bucket glue-tutorial-2026 --key output/

# Upload a sample CSV to the raw/ prefix
aws s3 cp orders.csv s3://glue-tutorial-2026/raw/orders.csv

Any CSV works for this tutorial — a handful of columns like order_id, customer_id, order_date, and amount is enough to demonstrate a real transform in Step 6. Keep raw data and Glue scripts in separate prefixes; it makes IAM scoping and cleanup much simpler once you have more than one pipeline in the same bucket.

Step 2: Create an IAM Role for Glue

Every Glue crawler and job runs with an IAM role that determines what it can read and write. Attach the AWS-managed AWSGlueServiceRole policy as a baseline, then add a scoped inline policy granting access to your specific bucket.

aws iam create-role \
  --role-name AWSGlueServiceRole-tutorial \
  --assume-role-policy-document '{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Allow",
      "Principal": {"Service": "glue.amazonaws.com"},
      "Action": "sts:AssumeRole"
    }]
  }'

aws iam attach-role-policy \
  --role-name AWSGlueServiceRole-tutorial \
  --policy-arn arn:aws:iam::aws:policy/service-role/AWSGlueServiceRole

aws iam put-role-policy \
  --role-name AWSGlueServiceRole-tutorial \
  --policy-name GlueTutorialS3Access \
  --policy-document '{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:PutObject", "s3:ListBucket"],
      "Resource": [
        "arn:aws:s3:::glue-tutorial-2026",
        "arn:aws:s3:::glue-tutorial-2026/*"
      ]
    }]
  }'

Scoping the S3 policy to just your tutorial bucket, rather than granting broad S3 access, is the difference between a Glue job that can only touch what it needs and one that could silently read or overwrite unrelated data in your account.

Step 3: Create a Glue Database in the Data Catalog

The Data Catalog organizes tables into databases, the same way a traditional relational database would, except a Glue database is just a metadata namespace — it holds no data itself, only pointers to where the data lives in S3 and what its schema looks like.

aws glue create-database \
  --database-input '{
    "Name": "glue_tutorial_db",
    "Description": "Tutorial database for the Glue walkthrough",
    "LocationUri": "s3://glue-tutorial-2026/"
  }'

Once this exists, both a crawler and any Glue job can reference glue_tutorial_db as the destination for whatever tables they define or discover, and downstream tools like Athena will see the same database immediately since they all read from the same catalog.

Step 4: Create and Run a Glue Crawler

A crawler inspects the data at a given path, infers its schema, and registers it as a table in the Data Catalog — no manual schema definition required. Point one at the raw/ prefix from Step 1.

aws glue create-crawler \
  --name glue-tutorial-crawler \
  --role arn:aws:iam::123456789012:role/AWSGlueServiceRole-tutorial \
  --database-name glue_tutorial_db \
  --targets '{
    "S3Targets": [
      {"Path": "s3://glue-tutorial-2026/raw/"}
    ]
  }' \
  --table-prefix "raw_"

# Trigger it to run once immediately
aws glue start-crawler --name glue-tutorial-crawler

A crawler run typically takes a couple of minutes for a small sample dataset. Check its status and confirm the table landed in the catalog:

aws glue get-crawler --name glue-tutorial-crawler --query 'Crawler.State'
# "READY"  (once it finishes)

aws glue get-tables --database-name glue_tutorial_db --query 'TableList[].Name'
# ["raw_orders"]

Substitute the IAM role ARN with the one you created in Step 2, using your own account ID. Replace the placeholder account ID shown above with your actual AWS account ID before running these commands.

Step 5: Explore the Table Schema With Glue Studio or the CLI

Before writing any transformation logic, confirm the crawler inferred the schema correctly. The Glue Studio visual editor in the AWS console shows this graphically, or you can pull it directly with the CLI.

aws glue get-table --database-name glue_tutorial_db --name raw_orders \
  --query 'Table.StorageDescriptor.Columns'
[
  {"Name": "order_id", "Type": "string"},
  {"Name": "customer_id", "Type": "string"},
  {"Name": "order_date", "Type": "string"},
  {"Name": "amount", "Type": "double"}
]

If a column comes back typed as string when you expected a date or number, that’s usually a sign the source CSV has inconsistent formatting in that column — worth fixing at the source before it becomes a transformation-time headache in Step 6.

Step 6: Write a Glue ETL Job in Python

With a cataloged source table, write the actual transformation: read the raw orders, cast order_date to a real date type, filter out any rows with a null customer_id, and write the result back to S3 as partitioned Parquet — a far more efficient format for downstream querying than the original CSV.

import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
from pyspark.sql.functions import to_date, col

args = getResolvedOptions(sys.argv, ['JOB_NAME'])
sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session
job = Job(glueContext)
job.init(args['JOB_NAME'], args)

# Read the crawled table from the Data Catalog
raw_orders = glueContext.create_dynamic_frame.from_catalog(
    database="glue_tutorial_db",
    table_name="raw_orders"
).toDF()

# Transform: cast order_date, drop rows with missing customer_id
cleaned = (
    raw_orders
    .withColumn("order_date", to_date(col("order_date"), "yyyy-MM-dd"))
    .filter(col("customer_id").isNotNull())
)

# Write partitioned Parquet output back to S3
cleaned.write.mode("overwrite").partitionBy("order_date") \
    .parquet("s3://glue-tutorial-2026/output/orders_cleaned/")

job.commit()

Upload the script to the scripts/ prefix, then register the job pointing to it, targeting the Glue 5.1 runtime.

aws s3 cp orders_etl.py s3://glue-tutorial-2026/scripts/orders_etl.py

aws glue create-job \
  --name orders-etl-job \
  --role arn:aws:iam::123456789012:role/AWSGlueServiceRole-tutorial \
  --command '{
    "Name": "glueetl",
    "ScriptLocation": "s3://glue-tutorial-2026/scripts/orders_etl.py",
    "PythonVersion": "3"
  }' \
  --glue-version "5.1" \
  --number-of-workers 2 \
  --worker-type G.1X \
  --default-arguments '{
    "--job-language": "python",
    "--enable-metrics": "true",
    "--enable-continuous-cloudwatch-log": "true",
    "--enable-glue-datacatalog": "true"
  }'

Two G.1X workers is a reasonable starting size for a small dataset. Each Data Processing Unit (DPU) provides 4 vCPUs and 16 GB of memory, so start modest and scale up only if the job’s CloudWatch metrics show it’s memory- or CPU-bound, which we’ll cover in the pricing and troubleshooting sections. Glue also offers a G.2X worker type with double the vCPUs and memory per DPU for memory-intensive jobs, and G.025X for lightweight jobs that don’t need a full DPU’s worth of compute — picking the right worker type matters as much as picking the right worker count once you move past a small sample dataset.

Step 7: Run the Job and Check the Output

Start the job and poll its status until it succeeds.

aws glue start-job-run --job-name orders-etl-job
# Returns a JobRunId, e.g. "jr_8f2e1c9a4b7d6e3f2a1b0c9d8e7f6a5b"

aws glue get-job-run --job-name orders-etl-job --run-id jr_8f2e1c9a4b7d6e3f2a1b0c9d8e7f6a5b \
  --query 'JobRun.JobRunState'
# "RUNNING" then "SUCCEEDED"

Once it succeeds, confirm the partitioned Parquet output landed in S3:

aws s3 ls s3://glue-tutorial-2026/output/orders_cleaned/ --recursive
# output/orders_cleaned/order_date=2026-08-15/part-00000-...snappy.parquet
# output/orders_cleaned/order_date=2026-08-16/part-00000-...snappy.parquet

The partition-per-date folder structure is exactly what makes this data cheap and fast to query later — Athena or Redshift Spectrum can skip entire partitions that don’t match a query’s date filter instead of scanning the whole dataset.

Step 8: Catalog the Transformed Output With a Second Crawler

The ETL job wrote data to S3, but nothing has cataloged it yet. Run a second crawler against the output/ prefix so the cleaned, partitioned table becomes queryable.

aws glue create-crawler \
  --name glue-tutorial-output-crawler \
  --role arn:aws:iam::123456789012:role/AWSGlueServiceRole-tutorial \
  --database-name glue_tutorial_db \
  --targets '{
    "S3Targets": [
      {"Path": "s3://glue-tutorial-2026/output/orders_cleaned/"}
    ]
  }' \
  --table-prefix "clean_"

aws glue start-crawler --name glue-tutorial-output-crawler

This crawler also picks up the order_date partitions automatically and registers them as a partitioned column in the catalog, which is what lets partition pruning work when you query the table.

Step 9: Query the Result With Amazon Athena

Because Athena reads from the same Glue Data Catalog, the cleaned table is queryable with standard SQL the moment the output crawler finishes — no loading step required.

SELECT order_date, COUNT(*) AS order_count, SUM(amount) AS total_amount
FROM glue_tutorial_db.clean_orders_cleaned
WHERE order_date >= DATE '2026-08-01'
GROUP BY order_date
ORDER BY order_date;

This is the payoff of the whole pipeline: raw CSV in, queryable partitioned Parquet out, with the schema and partitioning handled automatically by the two crawlers instead of hand-written DDL.

Step 10: Schedule the Pipeline to Run Automatically

A pipeline you have to trigger by hand isn’t a pipeline. Attach a schedule directly to the crawler and job so new data lands and gets processed without manual intervention.

# Schedule the raw crawler to run nightly at 2 AM UTC
aws glue update-crawler \
  --name glue-tutorial-crawler \
  --schedule "cron(0 2 * * ? *)"

# Create a Glue trigger to run the ETL job right after the crawler finishes
aws glue create-trigger \
  --name orders-etl-after-crawl \
  --type CONDITIONAL \
  --predicate '{
    "Conditions": [{
      "CrawlerName": "glue-tutorial-crawler",
      "CrawlState": "SUCCEEDED",
      "LogicalOperator": "EQUALS"
    }]
  }' \
  --actions '[{"JobName": "orders-etl-job"}]' \
  --start-on-creation

Chaining the ETL job to fire off a successful crawler run, rather than scheduling both independently, avoids the race condition where the job runs against yesterday’s crawl because the crawler hadn’t finished yet.

Step 11: Monitor With CloudWatch Metrics and Logs

Every Glue job with --enable-continuous-cloudwatch-log and --enable-metrics set, as configured in Step 6, streams both driver and executor logs into CloudWatch and publishes job-level metrics like memory usage, CPU load, and active executors.

aws logs tail /aws-glue/jobs/output --follow

aws cloudwatch get-metric-statistics \
  --namespace Glue \
  --metric-name glue.driver.aggregate.numFailedTasks \
  --dimensions Name=JobName,Value=orders-etl-job Name=JobRunId,Value=jr_8f2e1c9a4b7d6e3f2a1b0c9d8e7f6a5b \
  --start-time 2026-08-21T00:00:00Z --end-time 2026-08-21T23:59:59Z \
  --period 300 --statistics Sum

Set a CloudWatch alarm on job failures so a broken pipeline surfaces immediately rather than being discovered when a downstream Athena query returns stale data days later.

Step 12: Lock Down IAM and Cost Controls Before Production

Before this pipeline handles anything beyond sample data, run through a short hardening checklist:

  • Narrow the Glue job’s IAM role to only the specific S3 prefixes it reads from and writes to, instead of the whole bucket.
  • Set job bookmarks (--job-bookmark-option job-bookmark-enable) so reruns only process new data instead of reprocessing everything from scratch.
  • Tag every Glue job, crawler, and database with a cost-allocation tag so DPU-hour spend is traceable in Cost Explorer.
  • Set a maximum job timeout and a reasonable --number-of-workers ceiling so a runaway or stuck job doesn’t silently burn DPU-hours for hours.
  • If the job touches AWS Lake Formation-registered tables, confirm the job role has full table access, since Glue 5.0+ Spark jobs require that for read/write access to Lake Formation tables.
  • Turn on AWS CloudTrail logging for the Glue API if you need an audit trail of who created or modified jobs and crawlers.

Job bookmarks in particular save real money on recurring pipelines — without them, every scheduled run reprocesses the entire dataset instead of just what’s new since the last run.

Complete Working Project: A Scheduled Data Lake Pipeline

Put together, the 12 steps above produce a complete, self-running data lake pipeline. Here’s the full shape of it:

glue-tutorial-2026/  (S3 bucket)
├── raw/                          ← new CSVs land here
├── scripts/
│   └── orders_etl.py             ← the Spark ETL script from Step 6
└── output/
    └── orders_cleaned/
        ├── order_date=2026-08-15/
        └── order_date=2026-08-16/

Glue Data Catalog: glue_tutorial_db
├── raw_orders           ← from glue-tutorial-crawler
└── clean_orders_cleaned ← from glue-tutorial-output-crawler

Automation:
  glue-tutorial-crawler (nightly, cron) 
    → orders-etl-after-crawl (conditional trigger)
      → orders-etl-job (Glue 5.1, 2x G.1X)
        → glue-tutorial-output-crawler (manual or scheduled)
          → queryable in Athena

Drop a new CSV into the raw/ prefix, and the whole chain — crawl, transform, catalog, query — runs itself on the next scheduled cycle, with CloudWatch watching for failures the entire way. Extend it by swapping the CSV source for a JDBC connection to a production database, or adding a Glue Data Quality ruleset to reject rows that fail validation before they ever reach the output table.

The pattern scales well beyond a single orders table too. Add a second raw source, a second crawler, and a second transformation script, and you have a multi-table pipeline feeding the same catalog — the kind of setup that typically grows into a proper data lake as more teams start landing data in the raw/ prefix. Because the Data Catalog is shared infrastructure rather than something tied to a single job, adding sources doesn’t require redesigning anything you’ve already built; each new pipeline just adds its own tables alongside the existing ones.

AWS Glue Pricing in 2026: What It Actually Costs

Glue bills almost everything by the DPU-hour. According to the official AWS Glue pricing page, the rate is $0.44 per DPU-hour, billed per second with a one-minute minimum duration per run, and each DPU provides 4 vCPUs and 16 GB of memory. Crawlers, ETL jobs, and interactive sessions all bill at that same $0.44 per DPU-hour rate.

ComponentRateFree tierNotes
ETL jobs (Spark)$0.44 per DPU-hourNoneBilled per second, 1-minute minimum per run
Crawlers$0.44 per DPU-hourNoneSame rate as ETL; runs bill for actual crawl duration
Interactive sessions / Glue Studio$0.44 per DPU-hourNoneNo separate Glue Studio license fee
Data Catalog storage$1.00 per 100,000 objects/month beyond free tierFirst 1,000,000 objects free/monthObjects = tables, partitions, and database entries
Data Catalog requests$1.00 per 1,000,000 requests/month beyond free tierFirst 1,000,000 requests free/monthCovers API calls like GetTable and GetPartitions

For the tutorial project in this article, running two G.1X workers (2 DPUs) for a few minutes per job run costs a small fraction of a dollar, and the Data Catalog usage stays well inside the free 1-million-object, 1-million-request tier for anything short of a genuinely large production catalog. The real cost driver in production is DPU-hours on large, frequent Spark jobs — that’s where right-sizing worker count and worker type (Step 6) and enabling job bookmarks (Step 12) actually move the bill.

AWS Glue vs Databricks vs Apache Airflow vs Fivetran

Glue rarely competes head-to-head with these tools; more often it’s paired with one of them. Glue is positioned as serverless, AWS-native ETL with a catalog that’s shared across Athena, Redshift Spectrum, EMR, and Lake Formation, which makes it the default choice for teams already committed to AWS looking for managed Spark ETL without operating a cluster. Databricks is typically preferred for large-scale collaborative lakehouse analytics and ML workflows, especially across multiple clouds, and interoperates with Glue-managed data through shared Delta Lake or Iceberg tables rather than replacing it outright. Apache Airflow is primarily an orchestrator, not an ETL engine — many teams use Airflow to schedule and chain Glue jobs (or use AWS Step Functions for the same purpose within AWS), while Glue does the actual Spark transformation work; see our Step Functions vs Airflow comparison for how those two orchestration options stack up. Fivetran, by contrast, focuses on managed ELT connectors from SaaS apps into a warehouse, where Glue is the better fit for custom, heavier transformations rather than plug-and-play ingestion.

ToolCategoryWhere it fits with Glue
AWS GlueServerless ETL + catalogThe transformation and cataloging engine itself
DatabricksLakehouse analytics + ML platformOften reads the same Iceberg/Delta tables Glue writes
Apache AirflowWorkflow orchestrationSchedules and chains Glue jobs alongside other tasks
FivetranManaged SaaS-to-warehouse ELTHandles ingestion; Glue handles custom transformation

If your pipeline eventually needs to move data between warehouses too, it’s worth comparing the destination platforms directly — see our AWS RDS vs Azure Database vs Google Cloud SQL breakdown for the relational side, or our look at streaming ingestion in Kafka vs Kinesis if your raw/ prefix should really be a stream instead of a batch drop.

Common Pitfalls When Building on AWS Glue

These are the mistakes that eat the most time and budget on a first Glue project. None of them are exotic — they’re defaults that look harmless in a small tutorial dataset and turn into real cost or data-quality problems the moment production-scale data shows up.

  • Skipping job bookmarks on recurring jobs. Without --job-bookmark-option job-bookmark-enable, every scheduled run reprocesses the entire source dataset instead of only new data, quietly multiplying your DPU-hour bill.
  • Over-provisioning DPUs before checking actual usage. Jumping straight to 10 workers for a small dataset wastes money; start with 2 and scale up only after CloudWatch metrics show the job is genuinely memory- or CPU-bound.
  • Granting the Glue IAM role broad S3 access. Scoping to the exact bucket and prefixes the job needs, as shown in Step 2, limits the blast radius if a script has a bug or the role is ever compromised.
  • Not re-crawling after a schema change at the source. If upstream columns are added, removed, or change type, the catalog won’t reflect it until the crawler runs again, which can cause silent data quality issues downstream.
  • Writing output without partitioning. Skipping partitionBy on the write step, as used in Step 6, means every downstream Athena query scans the entire dataset instead of pruning to relevant partitions — slower and more expensive at any real scale.
  • Assuming Glue Studio and hand-written Spark scripts are interchangeable without review. Glue Studio-generated jobs are a great starting point, but they’re worth reading through before production, since visual-editor output can include steps or defaults you didn’t intend.

Troubleshooting: 8 AWS Glue Errors and How to Fix Them

Here are the errors most likely to interrupt a Glue project, and the fastest fix for each. When a fix isn’t obvious from the error message alone, the Glue job’s CloudWatch logs from Step 11, combined with the official Glue job monitoring documentation, are the fastest path to a root cause.

  • Job fails with an OutOfMemoryError or ExecutorLostFailure. The job is under-provisioned for its data volume. Increase the number of workers or move to a larger worker type (G.2X instead of G.1X), and check whether a wide, unpruned join is inflating memory use.
  • Crawler finishes but the table doesn’t appear in the catalog. Confirm the crawler’s IAM role actually has read access to the S3 path — a silent permissions failure is a far more common cause than a crawler bug.
  • Job reprocesses all data instead of only new records. Job bookmarks are disabled, misconfigured, or were reset. Check the --job-bookmark-option argument and confirm it’s set to job-bookmark-enable, not job-bookmark-disable.
  • “Access Denied” reading or writing a Lake Formation-registered table. Since Glue 5.0, Spark jobs need the job’s IAM role to have full table access under Lake Formation permissions specifically, separate from the underlying S3 IAM policy.
  • Schema mismatch between the catalog and the actual S3 data. Usually means the crawler hasn’t run since the source data’s structure changed. Re-run the crawler, or manually edit the table definition if the change is deliberate and you want to skip a re-crawl.
  • Job runs successfully but output is empty. Check the transformation logic for an overly aggressive filter — a null-check or date-cast that silently drops every row is the most common cause, and it won’t throw an error, it’ll just produce zero output rows.
  • Crawler and ETL job run out of order. If they’re scheduled independently rather than chained, the job can run against a stale or incomplete crawl. Use a conditional trigger, as shown in Step 10, so the job only fires after the crawler succeeds.
  • Job takes far longer than expected on a small dataset. Startup and cluster provisioning time adds a baseline delay to every Glue job regardless of data size. If that startup overhead is a problem for latency-sensitive pipelines, evaluate whether a Lambda-based approach or a persistent EMR cluster fits better than a Glue Spark job for that specific workload.

Advanced Tips: Iceberg Tables, Lake Formation, and Glue for Ray

Once the basic crawl-transform-catalog loop from this tutorial is solid, three more advanced capabilities are worth exploring for larger or more demanding pipelines.

SageMaker Lakehouse and Unified Studio Integration

Glue 5.0 added support for Amazon SageMaker Unified Studio and SageMaker Lakehouse, which brings Glue-cataloged tables directly into SageMaker’s notebook and ML tooling without a separate export or copy step. If your pipeline’s ultimate destination is a machine learning feature set rather than a BI dashboard, that integration is worth exploring once the base ETL pattern from this tutorial is working, since it removes an entire data-movement step between cataloging and model training.

Open table formats. Glue 5.0 and 5.1 ship with updated support for Apache Iceberg 1.7.1, Apache Hudi 0.15.0, and Delta Lake 3.3.0. Writing your output as Iceberg instead of plain partitioned Parquet, as this tutorial’s project does, adds schema evolution, time travel, and safe concurrent writes — genuinely useful once more than one job writes to the same table.

Lake Formation integration. For fine-grained, column- and row-level access control on top of the Data Catalog, Lake Formation lets you grant permissions per table, column, or even row filter rather than relying purely on IAM. Since a June 2025 AWS update, Glue 5.0+ Spark jobs can read and write Lake Formation-registered tables directly, provided the job role has full table access — worth adopting if multiple teams share the same catalog and need different visibility into the same tables.

Glue for Ray. For distributed Python workloads that don’t map cleanly onto Spark’s DataFrame model — custom feature engineering, certain ML preprocessing steps — Glue supports running that logic on Ray instead, still billed on the same DPU model as Spark jobs. It’s a narrower use case than the Spark ETL in this tutorial, but worth knowing about if a future pipeline needs distributed Python rather than distributed SQL-like transforms.

Frequently Asked Questions

Is AWS Glue free to use?
There’s no dedicated free tier for Glue compute — ETL jobs, crawlers, and interactive sessions all bill at $0.44 per DPU-hour from the first second. The Data Catalog does have a real free tier: the first 1,000,000 objects stored and 1,000,000 requests per month.

What Glue version should I use for a new project in 2026?
Glue 5.1, the current latest release as of November 2025, running Apache Spark 3.5.6, Python 3.11, and Scala 2.12.18. There’s no reason to start a new project on 4.0 or earlier.

Do I need to write Spark code to use Glue?
Not necessarily. Glue Studio’s visual editor generates Spark jobs from a drag-and-drop interface, and Glue DataBrew offers a no-code path for data preparation and cleaning. This tutorial writes the ETL script by hand for clarity and control, but either path produces a job that runs the same way underneath.

How is Glue different from Amazon EMR?
EMR gives you a managed Hadoop/Spark cluster you control the sizing, tuning, and lifecycle of. Glue is serverless — you don’t manage cluster infrastructure at all, just DPU count per job — at the cost of some of the fine-grained tuning control EMR offers.

What’s the difference between a Glue crawler and a Glue job?
A crawler discovers schema and registers tables in the Data Catalog; it doesn’t transform data. A job actually processes data — reading, transforming, and writing it — typically using Spark. Most real pipelines use both, as this tutorial’s project does.

Can Glue read from a database instead of S3?
Yes, via JDBC connections to sources like PostgreSQL, MySQL, or Amazon RDS instances, in addition to S3. The crawler and job patterns in this tutorial work the same way against a JDBC source once the connection is configured.

Why does my job keep reprocessing the same data?
Job bookmarks are almost certainly disabled or misconfigured. Set --job-bookmark-option job-bookmark-enable in the job’s default arguments, as covered in Step 12 and the troubleshooting section.

Is there a formal comparison of Glue’s market position against Databricks or Airflow?
Not from a major independent research firm in current public data. What’s clear from AWS’s own product positioning and third-party pricing guides is that Glue is typically paired with, rather than pitted against, tools like Airflow (orchestration) and Databricks (broader lakehouse analytics), each covering a different layer of the same pipeline.

How do I know if my Glue job needs more DPUs?
Check the CloudWatch metrics enabled in Step 6 and Step 11. Consistently high memory utilization or executor failures point to needing more workers or a larger worker type; consistently low utilization across a long-running job usually means you’re over-provisioned and paying for idle capacity.

Where to Go Next

You now have a complete, scheduled, monitored Glue pipeline running on the current 5.1 runtime: raw CSV crawled into the catalog, transformed into partitioned Parquet by a Spark ETL job, re-cataloged, and queryable in Athena on a nightly schedule. From here, the natural next steps are moving the output table to Iceberg for schema evolution, layering in Lake Formation for column-level access control, and right-sizing DPU usage against your actual production data volume.

Related Coverage

Nadia Dubois

Nadia Dubois

AI & Innovation Editor

Nadia Dubois is the AI & Innovation Editor at Tech Insider, where she tracks the rapid evolution of artificial intelligence, from foundation models to real-world enterprise deployment. She previously covered AI and startups for La Tribune and contributed to MIT Technology Review's European coverage. Nadia specializes in generative AI, AI regulation, and the intersection of technology and European industrial policy. She holds a dual degree in Computational Linguistics and Journalism from Sciences Po Paris.

View all articles