This page requires JavaScript to display.
G
Unpacking...
← Cloud Platforms
Cloud Platforms

AWS Glue for Data Engineers

The Data Catalog, crawlers, a full PySpark ETL job, job settings, bookmarks, Iceberg writes, parallel JDBC reads, Data Quality, tuning and monitoring.

Contents
1. What AWS Glue Is 2. The Data Catalog 3. Crawlers 4. A Glue ETL Job (PySpark) 5. Job Settings, Workers & Special Parameters 6. Incremental Processing & Job Bookmarks 7. Writing Iceberg Tables from Glue 8. Reading Databases (JDBC) in Parallel 9. Glue Data Quality 10. Performance, Cost & Monitoring 11. Common Interview Questions

1. What AWS Glue Is

AWS Glue is a serverless data integration service. It combines a central metadata catalog with managed Spark (and Python) jobs, so you can discover, catalog, transform and load data without managing clusters.

ComponentPurpose
Data CatalogHive-compatible metastore of databases, tables and partitions, used by Athena, EMR, Redshift Spectrum and Lake Formation
CrawlersScan S3 or JDBC sources, infer schemas and partitions, and create or update catalog tables
ETL jobsSpark (PySpark/Scala), Spark Streaming, and Python shell jobs, billed per DPU-hour
Glue StudioVisual job authoring and job monitoring
Triggers and workflowsSchedule or chain jobs and crawlers (Step Functions or Airflow are common alternatives)
Data QualityDeclarative data-quality rules (DQDL) on tables or inside jobs
ConnectionsJDBC, MongoDB, Kafka and other source definitions, with VPC and Secrets Manager integration
Schema RegistryAvro/JSON/Protobuf schema versioning and compatibility for streaming data
DataBrewNo-code visual data preparation for analysts

2. The Data Catalog

aws glue create-database --database-input '{"Name": "silver", "Description": "Cleaned and conformed data"}'
aws glue get-tables --database-name silver --query "TableList[].Name"
aws glue get-partitions --database-name silver --table-name transactions --max-items 5
import boto3
glue = boto3.client("glue")

# register a new partition yourself (cheaper and more predictable than re-running a crawler)
table = glue.get_table(DatabaseName="silver", Name="transactions")["Table"]
sd = dict(table["StorageDescriptor"])
sd["Location"] = "s3://acme-lake-prod/silver/transactions/dt=2026-10-26/"
glue.create_partition(DatabaseName="silver", TableName="transactions",
                      PartitionInput={"Values": ["2026-10-26"], "StorageDescriptor": sd})

3. Crawlers

aws glue create-crawler --name raw-transactions-crawler \
  --role arn:aws:iam::111122223333:role/glue-crawler-role \
  --database-name raw \
  --targets '{"S3Targets": [{"Path": "s3://acme-lake-prod/raw/transactions/"}]}' \
  --schedule "cron(15 2 * * ? *)" \
  --recrawl-policy '{"RecrawlBehavior": "CRAWL_NEW_FOLDERS_ONLY"}' \
  --schema-change-policy '{"UpdateBehavior": "LOG", "DeleteBehavior": "LOG"}'

aws glue start-crawler --name raw-transactions-crawler
SettingWhy
CRAWL_NEW_FOLDERS_ONLYIncremental crawling: much faster and cheaper on large datasets
Schema change policy LOGRecord schema changes instead of silently altering production tables
Table grouping / exclusionsStop the crawler from creating one table per folder or picking up _SUCCESS and temp files

Crawlers are great for discovery and messy raw zones. For stable curated tables, define the schema in code and add partitions explicitly: fewer surprises and lower cost.

4. A Glue ETL Job (PySpark)

import sys
from awsglue.utils import getResolvedOptions
from awsglue.context import GlueContext
from awsglue.dynamicframe import DynamicFrame
from awsglue.transforms import ApplyMapping
from awsglue.job import Job
from pyspark.context import SparkContext
from pyspark.sql import functions as F

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

# read only one partition from the catalog (push-down predicate prunes the S3 listing)
src = glueContext.create_dynamic_frame.from_catalog(
    database="raw", table_name="transactions",
    push_down_predicate=f"ingest_date = '{args['run_date']}'",
    transformation_ctx="src")  # transformation_ctx enables job bookmarks

mapped = ApplyMapping.apply(frame=src, mappings=[
    ("txn_id", "string", "txn_id", "string"),
    ("account_id", "string", "account_id", "string"),
    ("amount", "string", "amount", "decimal(18,2)"),
    ("event_ts", "string", "event_ts", "timestamp"),
], transformation_ctx="mapped")

df = (mapped.toDF()  # switch to a Spark DataFrame for logic
      .dropDuplicates(["txn_id"])
      .filter(F.col("amount").isNotNull())
      .withColumn("dt", F.to_date("event_ts")))

glueContext.write_dynamic_frame.from_options(
    frame=DynamicFrame.fromDF(df, glueContext, "out"),
    connection_type="s3",
    connection_options={"path": "s3://acme-lake-prod/silver/transactions/", "partitionKeys": ["dt"]},
    format="glueparquet",
    transformation_ctx="sink")

job.commit()  # saves bookmark state
aws glue create-job --name raw-to-silver-transactions \
  --role arn:aws:iam::111122223333:role/glue-etl-role \
  --glue-version "5.0" --worker-type G.1X --number-of-workers 10 \
  --command '{"Name": "glueetl", "ScriptLocation": "s3://acme-code/glue/raw_to_silver.py", "PythonVersion": "3"}' \
  --default-arguments '{"--job-bookmark-option": "job-bookmark-enable", "--enable-metrics": "true",
                        "--enable-continuous-cloudwatch-log": "true", "--enable-auto-scaling": "true"}'

aws glue start-job-run --job-name raw-to-silver-transactions --arguments '{"--run_date": "2026-10-26"}'
aws glue get-job-runs --job-name raw-to-silver-transactions --max-items 3

5. Job Settings, Workers & Special Parameters

SettingMeaning
Glue versionBundles Spark and Python versions (e.g. Glue 4.0 = Spark 3.3, Glue 5.0 = Spark 3.5); newer versions start faster and run faster
Worker typesG.1X (1 DPU = 4 vCPU/16 GB), G.2X, G.4X, G.8X for memory-heavy work; G.025X for small streaming jobs
Auto scalingAdds and removes workers during the run, up to the configured maximum
Flex executionCheaper spare capacity for non-urgent jobs (may start later)
--job-bookmark-optionjob-bookmark-enable / disable / pause
--additional-python-modulespip packages to install, e.g. great_expectations==1.2.0
--extra-py-filesYour own zipped modules on S3
--datalake-formatsiceberg, delta or hudi: loads the table-format libraries
--confSpark configuration, e.g. Iceberg catalog settings
--TempDirS3 scratch location (used by Redshift connectors and others)

6. Incremental Processing & Job Bookmarks

Job bookmarks remember what a job already processed, so the next run reads only new data: new S3 files (by modification time) or new JDBC rows (by a monotonically increasing key column).

7. Writing Iceberg Tables from Glue

# job parameters:
#   --datalake-formats  iceberg
#   --conf  spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions
#           --conf spark.sql.catalog.glue_catalog=org.apache.iceberg.spark.SparkCatalog
#           --conf spark.sql.catalog.glue_catalog.catalog-impl=org.apache.iceberg.aws.glue.GlueCatalog
#           --conf spark.sql.catalog.glue_catalog.warehouse=s3://acme-lake-prod/warehouse/
#           --conf spark.sql.catalog.glue_catalog.io-impl=org.apache.iceberg.aws.s3.S3FileIO

df.createOrReplaceTempView("updates")
spark.sql("""
    MERGE INTO glue_catalog.silver.customers t
    USING updates s
    ON t.customer_id = s.customer_id
    WHEN MATCHED AND s.op = 'D' THEN DELETE
    WHEN MATCHED THEN UPDATE SET *
    WHEN NOT MATCHED AND s.op <> 'D' THEN INSERT *
""")

8. Reading Databases (JDBC) in Parallel

# connection "orders-postgres" holds the JDBC URL, VPC subnet and a Secrets Manager secret
orders = glueContext.create_dynamic_frame.from_options(
    connection_type="postgresql",
    connection_options={
        "useConnectionProperties": "true",
        "connectionName": "orders-postgres",
        "dbtable": "public.orders",
        "hashfield": "order_id",  # split the read on this column…
        "hashpartitions": "16",  # …into 16 parallel queries
    },
    transformation_ctx="orders")

9. Glue Data Quality

from awsgluedq.transforms import EvaluateDataQuality

ruleset = """
Rules = [
    RowCount > 0,
    IsComplete "txn_id",
    IsUnique "txn_id",
    ColumnValues "amount" > 0,
    ColumnValues "channel" in ["UPI", "CARD_POS", "ATM", "NEFT"],
    Completeness "account_id" > 0.99
]
"""

dq_results = EvaluateDataQuality().process_rows(
    frame=DynamicFrame.fromDF(df, glueContext, "dq_input"),
    ruleset=ruleset,
    publishing_options={"dataQualityEvaluationContext": "silver_txn", "enableDataQualityResultsPublishing": True},
)

Results are published to CloudWatch and EventBridge, so a failed ruleset can stop a Step Functions pipeline or send an alert. Rules can also run directly against catalog tables on a schedule, without a job.

10. Performance, Cost & Monitoring

SymptomCheck / fix
Slow startUse Glue 4.0/5.0 (faster startup); for very short jobs, consider Python shell or Lambda
Many small input filesGroup files: {"groupFiles": "inPartition", "groupSize": "134217728"} in connection options
One task much slower than othersData skew: salt or repartition by a better key; see the Spark guide
Out of memoryBigger worker type (G.2X+), avoid collect(), fewer columns, broadcast small tables
Reads every partitionMissing push-down predicate or partition index
High costAuto scaling, Flex for non-urgent jobs, right-size workers, avoid idle interactive sessions

11. Common Interview Questions

QuestionShort answer
DynamicFrame vs DataFrame?DynamicFrames tolerate inconsistent schemas (choice types) and integrate with the catalog and bookmarks; DataFrames have the full Spark API. Convert with toDF() / DynamicFrame.fromDF()
How do job bookmarks work?They store which S3 files or JDBC key values were processed, per job; they need transformation_ctx and job.commit(), and do not detect updates to already-seen files
How do you speed up a Glue JDBC extract?Parallel reads with hashfield/hashpartitions (or a numeric partition column), push-down queries, and enough workers
Crawler vs defining tables yourself?Crawlers suit discovery and changing raw data; explicit DDL plus partition registration is more predictable for curated tables
What is a DPU?A unit of 4 vCPU and 16 GB memory; Glue bills per DPU-hour with per-second billing after a short minimum
Glue vs EMR?Glue: serverless, quick to adopt, pay per job. EMR: full cluster control, more frameworks and tuning, cheaper at large steady scale with spot
How do you handle small files in Glue?groupFiles/groupSize on read, coalesce/repartition before write, and compaction of table formats