An online retailer receives daily order exports. Finance needs corrected order totals without rebuilding every report. You will load a tiny order dataset into a lake and apply a late-arriving correction.
What you will build
A queryable Iceberg table containing three orders, with a corrected total of 149.00 for order 1002.
See the architecture before you build
AWS CLOUD Conceptual lab architecture
Raw ordersraw/orders.csv
Query & mergeEngine version 3
Curated lakeApache Iceberg / Parquet
AWS Glue Data Catalog · metadata used by Athena
Athena reads the raw CSV from S3, resolves table metadata in the Glue Data Catalog, and writes Iceberg data and metadata back to S3. SQL results are stored in a separate results prefix.
Where this fits in production
For production, add ingestion orchestration, deduplication before MERGE, schema checks, separate access to raw and curated prefixes, and an Iceberg maintenance policy. Choose this pattern for analytical corrections and batch reporting; do not use it as the checkout transaction database.
Know why each service belongs
Amazon S3
Durable object storage for files, application assets and data lakes.
Choose it when: Store objects independently of compute and retain multiple versions.
Consider the tradeoff: Use EBS for a block device or EFS for a shared file system.
An isolated AWS learning account and a role allowed to create S3 buckets, read/write/delete lab objects, run Athena queries and create/delete Glue databases and tables.
Use us-east-1 for all resources and Athena engine version 3. Lake Formation-managed accounts may also require catalog and data-location permissions.
Basic SQL knowledge. This exercise uses a general purpose S3 bucket with Iceberg tables, not the separate Amazon S3 Tables managed table-bucket service.
Cost & account preparation
AWS charges may apply for Athena bytes scanned, S3 storage/requests and Glue catalog usage. Use only the three-row sample; set an Athena workgroup scan limit. Free Tier eligibility varies by account.
Use a non-production account, sign in through an IAM role rather than root, and review AWS pricing. Budget alerts notify you; they do not automatically cap spending.
Open S3 → Create bucket. Choose a general purpose bucket in us-east-1 and a globally unique name such as cloudadhar-orders-YOUR-SUFFIX.
Keep Block all public access enabled, ACLs disabled and default SSE-S3 encryption. Create the bucket.
Throughout this lab, replace YOUR_BUCKET in SQL with this exact bucket name. Create raw/ and results/ folders. Keep curated/ empty until the table is created.
Checkpoint
The bucket is private and its region is us-east-1.
02
Upload the sample order export
Save the following text as orders.csv using a plain-text editor. Do not add extra blank lines.
Open raw/ → Upload → Add files, select orders.csv and upload. Keep only this file in raw/; Athena reads all data files in the table location.
s3://YOUR_BUCKET/raw/orders.csv contains a header and three order rows.
03
Configure Athena and register the raw table
Open Athena in us-east-1. Under Workgroups, create cloudadhar-orders using Athena SQL and engine version 3. Set the query result location to s3://YOUR_BUCKET/results/ and a per-query scan limit of 10 MB.
Open the query editor and select that workgroup and the AwsDataCatalog data source.
Run each SQL statement below separately. Replace YOUR_BUCKET first. The external table points to raw/ only.
SQL · run one statement at a time
CREATE DATABASE cloudadhar_orders;
CREATE EXTERNAL TABLE cloudadhar_orders.raw_orders (
order_id int, customer string, total double
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
STORED AS TEXTFILE
LOCATION 's3://YOUR_BUCKET/raw/'
TBLPROPERTIES ('skip.header.line.count'='1');
SELECT * FROM cloudadhar_orders.raw_orders ORDER BY order_id;
Checkpoint
The SELECT returns three rows; order 1002 has total 129.0.
Something not working?
If no output location is set, check the selected workgroup. AccessDenied can indicate S3, Glue, workgroup or Lake Formation permissions. Do not resolve it by making the bucket public.
04
Create and populate the Iceberg table
Create a new Iceberg table using the statements below, running each separately.
Insert the raw data once. The curated prefix must not contain another table. DECIMAL preserves money values at two decimal places.
SQL
CREATE TABLE cloudadhar_orders.orders (
order_id int, customer string, total decimal(10,2)
)
LOCATION 's3://YOUR_BUCKET/curated/orders/'
TBLPROPERTIES ('table_type'='ICEBERG', 'format'='parquet');
INSERT INTO cloudadhar_orders.orders
SELECT order_id, customer, CAST(total AS decimal(10,2))
FROM cloudadhar_orders.raw_orders;
SELECT * FROM cloudadhar_orders.orders ORDER BY order_id;
Checkpoint
Three curated rows appear. In S3, curated/orders/ now contains Iceberg data and metadata.
Something not working?
Do not use CREATE EXTERNAL TABLE for the Iceberg table. If you insert twice, drop and recreate this disposable curated table before continuing; otherwise the data is duplicated.
05
Apply a correction and prove the result
Finance corrects order 1002 to 149.00. Run the MERGE, then the SELECT separately.
Run the same MERGE a second time and repeat the SELECT. The row count and total should remain unchanged. This sample uses one source record per order key.
SQL
MERGE INTO cloudadhar_orders.orders t
USING (SELECT 1002 AS order_id, CAST(149.00 AS decimal(10,2)) AS total) s
ON t.order_id = s.order_id
WHEN MATCHED THEN UPDATE SET total = s.total;
SELECT COUNT(*) AS order_count, SUM(total) AS revenue
FROM cloudadhar_orders.orders;
SELECT * FROM cloudadhar_orders.orders WHERE order_id = 1002;
Checkpoint
order_count = 3, revenue = 287.00, and Ravi’s total = 149.00. Save these results as your proof of work.
06
Clean up the lab
Run the statements below separately. DROP TABLE on the managed Iceberg table removes its data; use only the lab table names.
In S3, empty the entire lab bucket (including raw data and query results), then delete it. Do not delete any shared bucket.
Delete the cloudadhar-orders Athena workgroup. Verify the Glue database is gone and check that no lab objects remain.
SQL · cleanup
DROP TABLE cloudadhar_orders.orders;
DROP TABLE cloudadhar_orders.raw_orders;
DROP DATABASE cloudadhar_orders;
Checkpoint
The lab bucket, database, tables and workgroup no longer exist.
GO TO THE SOURCE
Official AWS references
Use these service guides and architecture frameworks to go deeper. The diagram above is an original teaching design, not an AWS-certified production blueprint.