Have you ever processed a CSV file only to discover that it contains duplicate IDs, missing values, or invalid records?
These data quality issues can affect dashboards, analytics pipelines, financial reports, and AI applications.
In this article, we'll explore DuckDB, an open-source analytical database, and build a small Python project that validates sales data using SQL. Then we'll look at how the same concept can be extended to Amazon S3 and AWS data-processing services.
A quick clarification: DuckDB is not a newly launched standalone managed AWS database service. AWS announced a planned acquisition of DuckLabs, the company behind DuckDB, in August 2026. AWS has also published an integration example using DuckDB with AWS Glue and Amazon S3 Tables.
References:
What Is DuckDB?
DuckDB is an in-process analytical database that supports SQL queries over analytical data, including CSV and Parquet files.
Unlike a traditional database server, DuckDB can run directly inside a Python application or script. This makes it useful for lightweight analytics, data transformations, and data quality checks.
You can use DuckDB to:
- Validate incoming datasets.
- Find duplicate records and missing values.
- Filter and aggregate large files.
- Build lightweight ETL workflows.
- Prepare clean datasets for analytics.
- Process data before loading it into a warehouse.
When combined with AWS, DuckDB can complement Amazon S3, AWS Glue, Amazon Athena, and other data services.
Our Mini Project: Sales Data Validation
We'll build a simple pipeline:
sales.csv
|
v
DuckDB + SQL Validation
|
+----> valid_sales.csv
|
+----> rejected_sales.csv
Our validation rules will check:
- Missing order IDs.
- Missing customer IDs.
- Duplicate order IDs.
- Zero, negative, or missing amounts.
- Invalid order statuses.
Step 1: Install DuckDB
Make sure Python is installed, then run:
pip install duckdb
Create this project structure:
duckdb-aws-validation/
├── sales.csv
└── validate_sales.py
Step 2: Create Sample Data
Create sales.csv:
order_id,customer_id,amount,status
1001,C01,250,COMPLETED
1002,C02,150,PENDING
1002,C03,300,COMPLETED
1004,,100,COMPLETED
1005,C05,-50,COMPLETED
1006,C06,90,UNKNOWN
The file contains intentionally invalid records:
- Order
1002appears twice. - Order
1004has a missing customer ID. - Order
1005has a negative amount. - Order
1006has an invalid status.
Step 3: Validate Data Using DuckDB
Create validate_sales.py:
import duckdb
con = duckdb.connect("validation.duckdb")
# Load the CSV file
con.execute("""
CREATE OR REPLACE TABLE sales AS
SELECT *
FROM read_csv_auto('sales.csv')
""")
# Apply validation rules
con.execute("""
CREATE OR REPLACE TABLE validated_sales AS
SELECT *,
CASE
WHEN order_id IS NULL
THEN 'Missing order ID'
WHEN customer_id IS NULL
OR trim(customer_id) = ''
THEN 'Missing customer ID'
WHEN amount IS NULL OR amount <= 0
THEN 'Invalid amount'
WHEN status NOT IN ('COMPLETED', 'PENDING')
THEN 'Invalid status'
WHEN order_id IN (
SELECT order_id
FROM sales
WHERE order_id IS NOT NULL
GROUP BY order_id
HAVING COUNT(*) > 1
)
THEN 'Duplicate order ID'
ELSE NULL
END AS validation_error
FROM sales
""")
# Export valid records
con.execute("""
COPY (
SELECT * EXCLUDE (validation_error)
FROM validated_sales
WHERE validation_error IS NULL
)
TO 'valid_sales.csv'
(HEADER, DELIMITER ',')
""")
# Export rejected records with error reasons
con.execute("""
COPY (
SELECT *
FROM validated_sales
WHERE validation_error IS NOT NULL
)
TO 'rejected_sales.csv'
(HEADER, DELIMITER ',')
""")
# Show validation statistics
summary = con.execute("""
SELECT
COUNT(*) AS total_rows,
COUNT(*) FILTER (
WHERE validation_error IS NULL
) AS valid_rows,
COUNT(*) FILTER (
WHERE validation_error IS NOT NULL
) AS rejected_rows
FROM validated_sales
""").fetchdf()
print(summary)
con.close()
Step 4: Run the Project
Execute:
python validate_sales.py
Expected results:
| Metric | Count |
|---|---|
| Total records | 6 |
| Valid records | 1 |
| Rejected records | 5 |
Both occurrences of order 1002 are rejected because the order ID is duplicated. This leaves only order 1001 as a valid record.
The script creates:
-
validation.duckdb— the local DuckDB database. -
valid_sales.csv— records that passed validation. -
rejected_sales.csv— rejected records with their error reasons.
This approach makes data quality problems visible instead of silently passing them into downstream systems.
Note: This example reports the first matching validation error for each row. For production workloads, you may want to capture multiple errors per record and add stricter schema and type checks.
How Can We Use This with AWS?
Now let's extend the project into an AWS data pipeline.
Step 5: Store Raw Data in Amazon S3
A simple bucket layout could look like this:
s3://my-data-quality-bucket/
raw/
sales.csv
validated/
valid_sales.csv
rejected/
rejected_sales.csv
Upload the source file using the AWS CLI:
aws s3 cp sales.csv \
s3://my-data-quality-bucket/raw/sales.csv
This command requires the AWS CLI to be configured and appropriate S3 permissions.
Step 6: Integrate DuckDB into an AWS Workflow
A possible architecture is:
- Upload raw CSV or Parquet data to Amazon S3.
- Start a processing workflow.
- Run DuckDB validation in a suitable compute environment.
- Write valid and rejected records to separate S3 locations.
- Monitor processing errors and validation counts.
- Make curated datasets available to analytics services.
Depending on your requirements, you could run the validation code in an AWS Glue job, an ECS container, or another suitable compute environment.
AWS has demonstrated using DuckDB within AWS Glue to read Parquet data from S3 and write Apache Iceberg tables to Amazon S3 Tables.
This is especially interesting when your pipeline needs to combine SQL-based processing with modern lakehouse storage.
Step 7: Query Validated Data
After validation, you can use Amazon Athena to query supported data formats stored in S3.
For example, you could analyze accepted sales records:
SELECT
status,
SUM(amount) AS total_sales
FROM sales
GROUP BY status;
In a real deployment, register the appropriate table in your AWS Glue Data Catalog and configure Athena to query the curated dataset.
For analytical workloads, consider storing validated data in Parquet rather than CSV. Parquet supports columnar storage and can reduce the amount of data scanned by analytical queries.
Where Does DuckDB Fit in the AWS Ecosystem?
| Service | Main purpose |
|---|---|
| DuckDB | Lightweight analytical SQL and data validation |
| Amazon S3 | Object storage for raw and processed data |
| AWS Glue | Managed data integration and ETL |
| Amazon Athena | SQL queries over supported data in S3 |
| Amazon Redshift | Data warehousing and analytics |
These tools are complementary, not interchangeable. The right architecture depends on data volume, workload frequency, concurrency, operational needs, and cost.
Security and Cost Considerations
Before using this pattern in production:
- Use least-privilege IAM roles for S3 access.
- Never hardcode AWS credentials in your application.
- Encrypt sensitive data at rest and in transit.
- Separate raw, validated, and rejected datasets.
- Monitor job failures and processing duration.
- Configure retention policies for rejected records.
- Test with realistic data volumes and memory requirements.
DuckDB can reduce the need for additional infrastructure in some workloads, but it does not automatically make every AWS pipeline cheaper. Measure compute, storage, data transfer, and execution costs before making a decision.
Final Thoughts
DuckDB makes SQL-based data validation accessible without requiring a separate database server for every small processing task.
By combining DuckDB with Amazon S3 and appropriate AWS compute services, you can create a useful quality gate that catches invalid data before it reaches dashboards, analytics platforms, or AI applications.
The biggest lesson from this project is simple:
Don't trust data just because it was successfully uploaded. Validate it, explain why records fail, and only promote trusted data to downstream systems.
If you're building AWS data pipelines, what would you add next: schema validation, automated testing, or a fully automated AWS Glue workflow?

Top comments (0)