Home DevOps AWS Glue: Serverless ETL and Data Catalog — Production Patterns and Pitfalls
Advanced 4 min · July 18, 2026

AWS Glue: Serverless ETL and Data Catalog — Production Patterns and Pitfalls

AWS Glue serverless ETL deep dive: internals, performance tuning, failure modes, and production gotchas from real incidents.

N
Naren Founder & Principal Engineer

20+ years shipping production infrastructure and CI/CD at scale. Notes here come from systems that actually shipped.

Follow
Production
production tested
July 18, 2026
last updated
2,466
articles · all by Naren
Before you start⏱ 35 min
  • AWS account with Glue, S3, and IAM permissions
  • Basic understanding of ETL concepts and Spark
  • Familiarity with Python or Scala for Glue jobs
  • Experience with AWS CLI or SDK for automation
 ● Production Incident 🔎 Debug Guide ⚙ Triage Commands
Quick Answer

AWS Glue automates ETL by crawling data sources into a central Data Catalog, then running Spark jobs on ephemeral clusters. You pay per DPU-hour, and the service handles scaling, logging, and retries. Use it for batch ETL, data lake cataloging, and schema evolution.

✦ Definition~90s read
What is AWS Glue?

AWS Glue is a fully managed, serverless ETL service that provides a Data Catalog (metadata store) and a Spark-based execution engine. It crawls data sources, catalogs schemas, and runs transformation jobs without provisioning infrastructure.

Imagine a librarian who automatically scans every book in your warehouse, writes down its title, author, and summary on index cards, then sorts them into a card catalog.
Plain-English First

Imagine a librarian who automatically scans every book in your warehouse, writes down its title, author, and summary on index cards, then sorts them into a card catalog. When you need to reorganize the books (transform data), the librarian hires a team of assistants (Spark executors) who work in a rented room (serverless cluster) and leave when done. You pay only for the time the assistants work.

⚙ Browser compatibility
Latest versions — ✓ supported
ChromeFirefoxSafariEdge

You've got terabytes of raw logs in S3, a dozen CSV exports from legacy systems, and a mandate to build a unified analytics view. The old way: spin up an EMR cluster, write Spark scripts, manage YARN, and pray the spot instances don't get reclaimed. That's what AWS Glue was built to kill — but it's not magic. I've seen Glue jobs silently fail at 3 AM because of a single corrupt Parquet file, and I've watched teams burn $10k on idle DPUs because they didn't understand auto-scaling. This isn't a tutorial. It's a field guide to making Glue work in production without getting burned. By the end, you'll know how to design robust Glue ETL pipelines, tune performance, handle failures, and avoid the traps that catch everyone.

Why Glue Exists: The Pain Before Serverless ETL

Before Glue, every ETL pipeline meant managing infrastructure. You'd launch an EMR cluster, configure Spark, handle spot instance interruptions, and write custom scripts for schema discovery. The Data Catalog didn't exist — you either hardcoded schemas or used Hive Metastore, which required its own servers. Glue solves two problems: 1) automatically cataloging data sources so you don't manually track schemas, and 2) running Spark jobs without provisioning clusters. But the trade-off is less control over execution environment and Spark config. You can't install custom libraries easily, and debugging is harder because you don't have direct SSH access to executors. For teams that value speed over fine-grained control, Glue is a win. For complex, latency-sensitive pipelines, consider EMR or Spark on Kubernetes.

glue_catalog_crawl.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# io.thecodeforge — DevOps tutorial

import boto3

glue = boto3.client('glue')

# Create a crawler for S3 data
response = glue.create_crawler(
    Name='s3-logs-crawler',
    Role='arn:aws:iam::123456789012:role/GlueServiceRole',
    DatabaseName='logs_db',
    Targets={'S3Targets': [{'Path': 's3://my-bucket/logs/'}]},
    SchemaChangePolicy={'UpdateBehavior': 'UPDATE_IN_DATABASE', 'DeleteBehavior': 'LOG'},
    Configuration='{"Version":1.0,"CrawlerOutput":{"Partitions":{"AddOrUpdateBehavior":"InheritFromTable"}}}'
)

# Start the crawler
glue.start_crawler(Name='s3-logs-crawler')
print("Crawler started. Check CloudWatch for progress.")
Output
Crawler started. Check CloudWatch for progress.
⚠ Production Trap: Crawler Overwrites Manual Schema Changes
If you manually alter a table schema in the Data Catalog, a subsequent crawler run with 'UpdateBehavior': 'UPDATE_IN_DATABASE' will overwrite your changes. Use 'LOG' to only log changes, or set UpdateBehavior to 'UPDATE_IN_DATABASE' only for specific crawlers.

Glue ETL Jobs: Anatomy of a Spark Job on Serverless

A Glue job is essentially a Spark application running on an ephemeral cluster. You write Python (PySpark) or Scala code, and Glue handles cluster provisioning, scaling, and teardown. The key differentiator from plain Spark is the Glue DynamicFrame — a distributed collection of records that supports schema inference and transformations like ResolveChoice (handles schema inconsistencies) and Relationalize (flattens nested data). Under the hood, DynamicFrames convert to Spark DataFrames for execution. The job runs on a cluster of worker nodes, each with a fixed number of DPUs (Data Processing Units). One DPU equals 4 vCPU and 16 GB memory. You choose the number of workers and worker type (Standard, G.1x, G.2x) based on data size and complexity. The job bookmarks track processed data to avoid reprocessing — critical for incremental loads.

glue_etl_job.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# io.thecodeforge — DevOps tutorial

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

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

# Read from Data Catalog table (crawled earlier)
dynamic_frame = glueContext.create_dynamic_frame.from_catalog(
    database="logs_db",
    table_name="raw_logs",
    transformation_ctx="raw_logs"
)

# Resolve schema conflicts: choose first type encountered
resolved = ResolveChoice.apply(frame=dynamic_frame, choice="make_cols", transformation_ctx="resolved")

# Filter out null user agents
filtered = Filter.apply(frame=resolved, f=lambda row: row["user_agent"] is not None, transformation_ctx="filtered")

# Write as Parquet with Snappy compression
glueContext.write_dynamic_frame.from_options(
    frame=filtered,
    connection_type="s3",
    connection_options={"path": args['S3_OUTPUT_PATH'], "partitionKeys": ["event_date"]},
    format="parquet",
    format_options={"compression": "snappy"},
    transformation_ctx="output"
)

job.commit()
Output
Job completed successfully. Output written to s3://output-bucket/logs_processed/ with event_date partitions.
💡Senior Shortcut: Use Bookmarks for Incremental Loads
Enable job bookmarks (set --enable-continuous-cloudwatch-log and --job-bookmark-option=job-bookmark-enable) to track processed files. This prevents reprocessing old data and reduces cost. But beware: bookmarks rely on file modification time — if you overwrite files, they won't be reprocessed unless you reset the bookmark.

Data Catalog: The Metadata Backbone

The Data Catalog is a managed Hive Metastore compatible with Athena, Redshift Spectrum, and EMR. It stores table definitions, partition metadata, and schema versions. Crawlers automatically populate it by scanning data sources. Each table has a location (S3 path), format (Parquet, CSV, etc.), and serde (serialization/deserialization) library. Partitions are stored as Hive-style directories (e.g., event_date=2025-01-01/). The Catalog supports schema versioning — you can view changes over time. Critical for production: the Catalog is eventually consistent. After a crawler updates a table, there's a propagation delay (seconds to minutes). If your job reads immediately after a crawler, it might see stale metadata. Always add a retry or delay. Also, the Catalog has a default limit of 100,000 tables per account — request a limit increase if you have many data sources.

catalog_query.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# io.thecodeforge — DevOps tutorial

import boto3

glue = boto3.client('glue')

# Get table metadata
table = glue.get_table(DatabaseName='logs_db', Name='raw_logs')
print("Table location:", table['Table']['StorageDescriptor']['Location'])
print("Columns:")
for col in table['Table']['StorageDescriptor']['Columns']:
    print(f"  {col['Name']}: {col['Type']}")

# List partitions
partitions = glue.get_partitions(DatabaseName='logs_db', TableName='raw_logs')
print(f"Number of partitions: {len(partitions['Partitions'])}")
Output
Table location: s3://my-bucket/logs/
Columns:
event_date: string
user_agent: string
status_code: int
response_time: double
Number of partitions: 42
⚠ Never Do This: Rely on Crawler for Real-Time Schema Updates
Crawlers are batch operations — they run on a schedule (e.g., every hour). If your pipeline adds new columns frequently, you'll have stale schemas. Instead, use Glue's UpdateTable API to programmatically update schemas after writes, or use Athena's CREATE TABLE AS SELECT (CTAS) to create tables with the correct schema.

Performance Tuning: DPUs, Workers, and Spark Config

Glue jobs run on worker types: Standard (1 DPU per worker), G.1x (4 DPU), G.2x (8 DPU). More DPUs means more parallelism, but also more shuffle overhead. The default max concurrency per job is 1 — you can increase it for parallel runs. Key Spark configs: spark.executor.memory (default 4GB for Standard), spark.driver.memory (default 4GB), spark.sql.shuffle.partitions (default 200). For large datasets, increase shuffle partitions to avoid OOM. Use spark.sql.adaptive.enabled=true for dynamic coalescing. Glue also supports auto-scaling — set --enable-auto-scaling=true. This adds workers up to the max you specify. But auto-scaling adds latency (2-5 min to scale up). For predictable workloads, set a fixed worker count. Monitor CloudWatch metrics: DPUUsage, JobRunTime, and ShuffleBytesWritten. If shuffle is high, increase parallelism or use bucketing.

glue_job_with_config.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# io.thecodeforge — DevOps tutorial

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

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

# Set Spark config for performance
spark.conf.set("spark.sql.shuffle.partitions", "400")
spark.conf.set("spark.sql.adaptive.enabled", "true")
spark.conf.set("spark.sql.adaptive.coalescePartitions.enabled", "true")

df = spark.read.parquet(args['S3_INPUT_PATH'])
# Perform transformations...
df.write.mode("overwrite").parquet(args['S3_OUTPUT_PATH'])

job.commit()
Output
Job completed with shuffle partitions set to 400. Adaptive coalescing reduced output partitions from 400 to 12.
🔥Interview Gold: Glue Auto-Scaling vs Fixed Workers
Auto-scaling adds workers based on load, but it takes time to scale. For bursty workloads, fixed workers with a higher count may be cheaper because jobs finish faster. Always benchmark both. The formula: cost = DPU-hours * price. A job that runs 10 min with 20 workers costs the same as 20 min with 10 workers, but the former may have less overhead.

Handling Failures: Retries, Alarms, and Dead Letter Queues

Glue jobs fail for many reasons: corrupt data, OOM, network timeouts, IAM permission changes. By default, Glue retries failed jobs up to 3 times with exponential backoff. But retries don't help if the root cause is a bad file. Implement a dead letter queue (DLQ) pattern: move failed records to an S3 bucket for manual inspection. Use Glue's job bookmark to skip already processed files after a retry. Set up CloudWatch alarms on JobRunState (FAILED) and DPUUsage (spikes). For critical pipelines, use AWS Step Functions to orchestrate Glue jobs with custom error handling (e.g., send SNS notification, pause pipeline). Also, enable continuous logging to CloudWatch (--enable-continuous-cloudwatch-log=true) to capture Spark driver and executor logs. Without it, you only get a summary — useless for debugging.

glue_dlq_pattern.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# io.thecodeforge — DevOps tutorial

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

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

df = spark.read.parquet(args['S3_INPUT_PATH'])

# Separate valid and invalid records
try:
    valid_df = df.filter(df["status_code"].isNotNull())
    invalid_df = df.filter(df["status_code"].isNull())
    
    # Write valid
    valid_df.write.mode("append").parquet(args['S3_OUTPUT_PATH'])
    
    # Write invalid to DLQ
    if invalid_df.count() > 0:
        invalid_df.write.mode("append").parquet(args['S3_DLQ_PATH'])
        print(f"Moved {invalid_df.count()} invalid records to DLQ")
except Exception as e:
    print(f"Job failed: {e}")
    raise

job.commit()
Output
Moved 150 invalid records to DLQ
⚠ Production Trap: Default Retries Mask Root Causes
Glue's automatic retries can hide transient issues. If a job fails due to a corrupt file, retrying will fail again. Always set up a DLQ and alert on retries. Use Step Functions for custom retry logic with backoff and notification.

Security: IAM Roles, Encryption, and VPC

Glue jobs run with an IAM role that needs permissions to read/write S3, access the Data Catalog, and optionally connect to JDBC sources. The role must have a trust policy for glue.amazonaws.com. For sensitive data, enable S3 server-side encryption (SSE-S3 or SSE-KMS) and use Glue's built-in encryption for the Data Catalog (set at catalog level). If your data is in a VPC (e.g., RDS, Redshift), you must attach a VPC to the Glue job. This adds a network interface per worker and can slow down S3 access. Use VPC endpoints for S3 and DynamoDB to avoid NAT gateway costs. Also, Glue supports AWS Lake Formation for fine-grained access control — you can restrict column-level access. But Lake Formation adds complexity; only use it if you need multi-team data sharing.

glue_vpc_job.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# io.thecodeforge — DevOps tutorial

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

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

# Read from RDS via JDBC (requires VPC)
df = spark.read.format("jdbc").options(
    url=args['JDBC_URL'],
    dbtable="orders",
    user=args['DB_USER'],
    password=args['DB_PASSWORD'],
    driver="com.mysql.cj.jdbc.Driver"
).load()

# Transform and write to S3
df.write.mode("overwrite").parquet("s3://my-bucket/orders/")

job.commit()
Output
Job completed. Orders table read from RDS and written to S3 as Parquet.
💡Senior Shortcut: Use Secrets Manager for DB Credentials
Never hardcode passwords in job parameters. Store them in AWS Secrets Manager and retrieve them at runtime using boto3. This avoids exposing secrets in CloudWatch logs and simplifies rotation.

Monitoring and Observability: Beyond CloudWatch

CloudWatch logs are the default, but they're noisy. Use structured logging (JSON) to filter easily. Glue emits metrics: DPUUsage, JobRunTime, BytesRead, BytesWritten, ShuffleBytesWritten. Set up dashboards for these. For Spark-specific metrics, enable the Spark UI (--enable-spark-ui=true) and view it via the Glue console or proxy. The Spark UI shows stages, tasks, and shuffle details — invaluable for tuning. Also, use Glue's job run insights (available in the console) to see bottlenecks. For alerting, create CloudWatch alarms on JobRunState (FAILED) and DPUUsage (if it drops unexpectedly, the job may be idle). Consider using AWS Distro for OpenTelemetry to send traces to X-Ray for end-to-end visibility.

glue_structured_logging.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# io.thecodeforge — DevOps tutorial

import sys
import json
import logging
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job

# Configure structured logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)

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

# Log with JSON
log_data = {"event": "job_start", "job_name": args['JOB_NAME'], "timestamp": spark.sparkContext.startTime}
logger.info(json.dumps(log_data))

# ... job logic ...

job.commit()
log_data = {"event": "job_end", "job_name": args['JOB_NAME'], "status": "success"}
logger.info(json.dumps(log_data))
Output
{"event": "job_start", "job_name": "my-job", "timestamp": 1700000000000}
{"event": "job_end", "job_name": "my-job", "status": "success"}
🔥Interview Gold: Spark UI in Glue
The Spark UI is available for 7 days after job completion. Use it to check task skew (some tasks take much longer than others), shuffle spill (data written to disk due to memory pressure), and stage failures. If you see high spill, increase executor memory or repartition.

When Not to Use Glue: Alternatives and Trade-offs

Glue is not a silver bullet. Avoid it when: 1) You need sub-minute latency — Glue jobs have a startup overhead of 1-5 minutes. Use AWS Lambda or Kinesis Data Analytics for streaming. 2) You need custom Spark libraries (e.g., MLlib with native dependencies) — Glue's environment is locked down. Use EMR or SageMaker. 3) You have complex multi-step workflows with branching — Glue jobs are single scripts. Use Step Functions to orchestrate multiple Glue jobs, but that adds complexity. 4) You need fine-grained cost control — Glue charges per DPU-hour regardless of utilization. For predictable workloads, reserved capacity (EMR) may be cheaper. 5) You need to debug with SSH — Glue doesn't allow direct access to executors. Use EMR if you need deep debugging. The rule of thumb: if your ETL fits in a single Spark script and you don't need custom environments, Glue is great. Otherwise, consider EMR, Athena, or custom Spark on Kubernetes.

⚠ Never Do This: Use Glue for Real-Time Streaming
Glue streaming jobs (based on Spark Structured Streaming) have a minimum checkpoint interval of 1 second and startup latency of minutes. For real-time (sub-second) needs, use Kinesis Data Analytics or Apache Flink on EMR.
● Production incidentPOST-MORTEMseverity: high

The 4GB Container That Kept Dying

Symptom
Glue job processing 500GB of JSON logs consistently failed after 2 hours with 'Container killed by YARN for exceeding memory limits'.
Assumption
We assumed the data was too large and needed more DPUs.
Root cause
The default Spark executor memory (4GB) was insufficient for the shuffle operations caused by a wide join. The job used coalesce(1) at the end, forcing all data into a single partition, which overflowed the executor.
Fix
Removed coalesce(1) and used repartition(10) for output. Set spark.executor.memory=8g and spark.shuffle.service.enabled=true. Job completed in 45 minutes.
Key lesson
  • Never coalesce to 1 unless you absolutely need a single file — it's a memory bomb.
  • Always monitor shuffle spill metrics in the Spark UI.
Production debug guideSystematic recovery paths for the failure modes engineers actually hit.3 entries
Symptom · 01
Job fails with 'AnalysisException: Path does not exist: s3://...'
Fix
1. Verify S3 path exists and IAM role has s3:GetObject permission. 2. Check if path is a directory (ends with '/') or file. 3. If using partition pruning, ensure partition columns exist in the schema.
Symptom · 02
Crawler completes but no tables created
Fix
1. Check crawler logs for 'Insufficient permissions' or 'No data found'. 2. Verify S3 path has readable files (not empty). 3. Ensure crawler IAM role has glue:CreateTable and glue:CreatePartition.
Symptom · 03
Job runs but no output written
Fix
1. Check job logs for 'No records to write' — filter may be too aggressive. 2. Verify output path exists and IAM role has s3:PutObject. 3. If using bookmarks, ensure files have newer timestamps than last bookmark.
★ AWS Glue: Serverless ETL and Data Catalog Triage Cheat SheetFirst-response commands for when things go wrong — copy-paste ready.
Job failed with `Container killed by YARN for exceeding memory limits`
Immediate action
Check Spark UI for shuffle spill metrics
Commands
aws glue get-job-run --job-name my-job --run-id <run-id> --query 'JobRun.SparkUIUrl'
aws logs get-log-events --log-group-name /aws-glue/jobs/error --log-stream-name <stream>
Fix now
Increase spark.executor.memory to 8g and set spark.sql.shuffle.partitions to 400
Crawler stuck in RUNNING state for >1 hour+
Immediate action
Check CloudWatch logs for crawler errors
Commands
aws glue get-crawler --name my-crawler --query 'Crawler.LastCrawl'
aws logs describe-log-streams --log-group-name /aws-glue/crawlers --query 'logStreams[?contains(logStreamName, `my-crawler`)]'
Fix now
Stop and restart crawler. If persists, check S3 path for large number of small files (crawler overhead).
Data Catalog table shows wrong column types+
Immediate action
Check crawler configuration for schema update policy
Commands
aws glue get-table --database-name my-db --name my-table --query 'Table.StorageDescriptor.Columns'
aws glue get-crawler --name my-crawler --query 'Crawler.SchemaChangePolicy'
Fix now
Update crawler to use 'UpdateBehavior': 'UPDATE_IN_DATABASE' and re-run. Or manually alter table via API.
Job fails with `java.lang.NoSuchMethodError`+
Immediate action
Check for conflicting library versions
Commands
aws glue get-job --job-name my-job --query 'Job.Command'
Check if using Python shell vs Spark — Python shell has limited libraries
Fix now
Use Glue version 3.0 or later with Spark 3.x. If using custom JARs, ensure compatibility.
FeatureAWS GlueAmazon EMR
Startup time1-5 min (cold start)5-15 min (cluster provisioning)
Cost modelPer DPU-hour (serverless)Per instance-hour (reserved or spot)
Custom librariesLimited (pre-installed Python/Scala)Full control (any AMI)
DebuggingCloudWatch logs + Spark UI (no SSH)SSH access to master/core nodes
Auto-scalingBuilt-in (adds workers)Manual or via Auto Scaling groups
Data CatalogManaged Glue CatalogHive Metastore (self-managed or Glue)
Best forSimple batch ETL, schema discoveryComplex pipelines, ML, custom environments
⚙ Quick Reference
7 commands from this guide
FileCommand / CodePurpose
glue_catalog_crawl.pyglue = boto3.client('glue')Why Glue Exists
glue_etl_job.pyfrom awsglue.transforms import *Glue ETL Jobs
catalog_query.pyglue = boto3.client('glue')Data Catalog
glue_job_with_config.pyfrom awsglue.transforms import *Performance Tuning
glue_dlq_pattern.pyfrom awsglue.transforms import *Handling Failures
glue_vpc_job.pyfrom awsglue.transforms import *Security
glue_structured_logging.pyfrom awsglue.transforms import *Monitoring and Observability

Key takeaways

1
Glue is serverless Spark with a managed Data Catalog
great for batch ETL, but not for real-time or custom environments.
2
Always enable job bookmarks and continuous logging
they save cost and debugging time.
3
Memory issues are the #1 cause of Glue job failures
tune Spark configs and use the Spark UI.
4
The Data Catalog is eventually consistent
add retries or delays after crawler runs.
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01SENIOR
How does Glue handle schema evolution when new columns appear in source ...
Q02SENIOR
When would you choose Glue over Athena for ETL?
Q03SENIOR
What happens when a Glue job runs out of memory during a shuffle? How do...
Q04JUNIOR
What is a Glue DynamicFrame and how does it differ from a Spark DataFram...
Q05SENIOR
You have a Glue job that reads from a JDBC source and writes to S3. The ...
Q06SENIOR
How would you design a Glue pipeline that processes 10TB of data daily w...
Q01 of 06SENIOR

How does Glue handle schema evolution when new columns appear in source data?

ANSWER
Glue's DynamicFrame uses ResolveChoice to handle schema inconsistencies. You can choose to make columns (add new columns), cast to a common type, or drop conflicting columns. For production, use 'make_cols' to preserve all data, then apply explicit schema in later transforms.
FAQ · 4 QUESTIONS

Frequently Asked Questions

01
What is the difference between AWS Glue and Amazon EMR for ETL?
02
How do I handle corrupt data in a Glue job?
03
Can I use Glue for real-time data processing?
04
How do I optimize Glue job costs?
N
Naren Founder & Principal Engineer

20+ years shipping production infrastructure and CI/CD at scale. Notes here come from systems that actually shipped.

Follow
Verified
production tested
July 18, 2026
last updated
2,466
articles · all by Naren
🔥

That's AWS. Mark it forged?

4 min read · try the examples if you haven't

Previous
Amazon Neptune: Graph Database for Connected Data
50 / 63 · AWS
Next
Amazon Athena: Serverless SQL Query Service