Partition Projection in AWS Athena
Athena Partition Projection, introduced in June 2020, eliminates the need to run MSCK REPAIR TABLE to add new partitions manually.
Athena Partition Projection, introduced in June 2020, eliminates the need to run MSCK REPAIR TABLE to add new partitions manually.
Building Backend
The key point in the CloudFormation template is the GlueTable.TableInput.Parameters section of the GlueTable definition (lines 27–35). This section enables Partition Projection with the following important properties:
projection.enabled: Enables partition projection.projection.year_month.format: Specifies the date format for partitions.projection.year_month.range: Defines the range for partitions, supportingNOWwith offsets (e.g.,NOW+9HOURS).
The projection.year_month.range property is treated as UTC. If you intend to use a different timezone, you need to specify the time difference using a format like NOW+9HOURS.
For more details, please refer to the official documentation.
AWSTemplateFormatVersion: "2010-09-09"Description: Stack for Athena partition projection sampleResources: S3: Type: AWS::S3::Bucket Properties: BucketName: athena-partition-projection-logs BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: AES256
GlueDatabase: Type: AWS::Glue::Database Properties: DatabaseInput: Name: sample CatalogId: !Ref AWS::AccountId
GlueTable: Type: AWS::Glue::Table Properties: DatabaseName: !Ref GlueDatabase CatalogId: !Ref AWS::AccountId TableInput: TableType: EXTERNAL_TABLE Parameters: classification: json "projection.enabled": true "projection.year_month.format": yyyy/MM "projection.year_month.interval": 1 "projection.year_month.interval.unit": MONTHS "projection.year_month.range": 2021/09,NOW "projection.year_month.type": date "storage.location.template": s3://athena-partition-projection-logs/${year_month} StorageDescriptor: Columns: - Name: id Type: int - Name: message Type: string Location: !Sub s3://${S3}/ InputFormat: org.apache.hadoop.mapred.TextInputFormat OutputFormat: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat Compressed: false NumberOfBuckets: 0 SerdeInfo: SerializationLibrary: org.openx.data.jsonserde.JsonSerDe Parameters: paths: id,message StoredAsSubDirectories: false PartitionKeys: - Name: year_month Type: string Retention: 0 Name: sample_logsDeploy the CloudFormation stack:
aws cloudformation deploy \ --template-file stack.yml \ --stack-name athena-partition-projection-sampleUploading Data
Some test data can then be uploaded to the S3 bucket:
echo '{"id": 1, "message": "hello"}' > 2021-09.jsonecho '{"id": 2, "message": "world"}' > 2021-10.jsonaws s3 cp 2021-09.json s3://athena-partition-projection-logs/2021/09/aws s3 cp 2021-10.json s3://athena-partition-projection-logs/2021/10/Verify that the files are uploaded:
aws s3 ls s3://athena-partition-projection-logs/2021/Querying Data
Fetching data from the 2021/09 partition confirms the projection works:
SELECT * FROM "sample"."sample_logs"WHERE year_month = '2021/09'LIMIT 10;Expected result:
1 hello 2021/09The 2021/10 partition behaves the same way:
SELECT * FROM "sample"."sample_logs"WHERE year_month = '2021/10'LIMIT 10;Expected result:
2 world 2021/10Cleaning Up
Remove the resources provisioned by this example with:
aws s3 rm --recursive s3://athena-partition-projection-logsaws cloudformation delete-stack --stack-name athena-partition-projection-sampleConclusion
Deploying a Glue table with partition projection enabled let Athena query newly uploaded year_month partitions immediately, with no MSCK REPAIR TABLE step in between. Setting projection.enabled: true alongside projection.year_month.range: 2021/09,NOW means Athena computes which partitions are valid mathematically, from the range and format, rather than looking them up in the Glue catalog — so there’s no catalog entry to update as each new month’s data lands. That computation depends entirely on the storage.location.template matching the actual S3 key layout, and since NOW is evaluated in UTC, any range meant to track a local calendar month needs an explicit offset like NOW+9HOURS or the projected partitions will drift from the data by however many hours the timezone is off.
Related posts
Querying S3 Logs with Athena and Kinesis Data Firehose
Piping logs into S3 through Kinesis Data Firehose and querying them with Athena, using custom prefixes so partitions register automatically.
Sign in with Slack Using Cognito User Pools and OIDC
Federating Cognito user pools with Slack over OIDC and wiring "Sign in with Slack" into a Next.js app with Amplify.
Deploying FastAPI on AWS Lambda with Lambda Web Adapter
This example guides you through the process of developing API backends with FastAPI using Lambda Web Adapter.
API Gateway WebSocket: Implementing a Mock Integration
Building an API Gateway WebSocket API entirely with mock integrations, returning canned responses with no backend Lambda involved.
Uploading to S3 Through CloudFront Pre-Signed URLs
CloudFront signed URLs let you upload to S3 through a custom domain—useful when direct S3 pre-signed URLs are not an option.
