Trying Out ALB's New Feature: Logging Integrated with CloudWatch Logs

Trying Out ALB's New Feature: Logging Integrated with CloudWatch Logs

ALB logs can now be delivered directly to CloudWatch Logs. This covers setup via the Vended Logs API, a comparison of the JSON, CSV and legacy-compatible formats, and measured delivery delays.
2026.07.24

This page has been translated by machine translation. View original

Introduction

On July 23, 2026, ALB access logs, connection logs, and health check logs, which previously could only be delivered to S3 buckets, became deliverable directly to CloudWatch Logs log groups via the Vended Logs API.

https://aws.amazon.com/jp/about-aws/whats-new/2026/07/amazon-cloudwatch-logs/

Item S3 Legacy CloudWatch Logs (Vended Logs)
Destination S3 bucket CloudWatch Logs log group
Configuration location Attributes tab / modify-load-balancer-attributes Integrations tab / Vended Logs API
Format Fixed space-delimited JSON / plain (tab / space / comma)
Field selection Not possible (all fields fixed) Not possible (all fields fixed)
Delivery delay 5 minutes/file Best effort
Delivery charge Free Vended Logs pricing ($0.50/GB to $0.05/GB)*
Storage charge S3 storage cost CWL storage cost

*Tokyo region, pricing as of July 2026

https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-cloudwatch-logs.html

Verification Details

Verification Environment

Item Value
Region ap-northeast-1 (Tokyo)
ALB alb-cwlogs-test (internet-facing)
Listener HTTP 80 → fixed-response 200
AWS CLI 2.36.7

Delivery Configuration

Delivery configuration consists of the following three steps.

  1. put-delivery-source — Register the ALB as the log delivery source
  2. put-delivery-destination — Register a CloudWatch Logs log group as the delivery destination
  3. create-delivery — Link the delivery source and destination, specify the format, and create the delivery

There are three supported log types.

  • ALB_ACCESS_LOGS
  • ALB_CONNECTION_LOGS
  • ALB_HEALTH_CHECK_LOGS

The output format and delimiter options are summarized in the table.

Format Delimiter Notes
json - JSON format
plain \t (tab) Plain text
plain (space) Legacy compatible
plain , (comma) CSV

You cannot pick and choose fields; all 34 fields for Access Logs, 15 for Connection Logs, and 10 for Health Check Logs are output.

Access Logs field list (34 fields)
  1. type
  2. time
  3. elb
  4. client_port
  5. target_port
  6. request_processing_time
  7. target_processing_time
  8. response_processing_time
  9. elb_status_code
  10. target_status_code
  11. received_bytes
  12. sent_bytes
  13. request_line
  14. user_agent
  15. ssl_cipher
  16. ssl_protocol
  17. target_group_arn
  18. trace_id
  19. domain_name
  20. chosen_cert_arn
  21. matched_rule_priority
  22. request_creation_time
  23. actions_executed
  24. redirect_url
  25. error_reason
  26. target_port_list
  27. target_status_code_list
  28. classification
  29. classification_reason
  30. conn_trace_id
  31. transformed_host
  32. transformed_uri
  33. request_transform_status
  34. ip_address

In the console, the new feature is configured from the Integrations tab.

Integrations tab (new UI)

The conventional S3 delivery (legacy) can be configured from the Attributes tab and remains available.

Attributes tab (old UI)

From the same delivery source, you can create multiple deliveries in parallel with different formats and different log groups. This time, I confirmed that the following three deliveries run simultaneously.

# Log group Format delimiter
1 /aws/alb/alb-cwlogs-test/access JSON -
2 /aws/alb/alb-cwlogs-test/access-csv plain , (CSV)
3 /aws/alb/alb-cwlogs-test/access-legacy plain (space)

Checking the Logs

I queried the access logs delivered in JSON format with CloudWatch Logs Insights.

fields @timestamp, type, elb_status_code, client_port, request_line, user_agent, actions_executed, conn_trace_id, ip_address
| sort @timestamp desc
| limit 10

I confirmed that all 6 requests sent during verification were delivered. With the JSON format, CloudWatch Logs Insights automatically parses the fields, so you can directly reference fields such as type and elb_status_code.

Example of JSON-format access log output
{
  "type": "http",
  "time": "2026-07-24T02:43:09.548878Z",
  "elb": "app/alb-cwlogs-test/xxxxxxxxxxxxxxxx",
  "client_port": "203.0.113.1:4979",
  "target_port": "-",
  "request_processing_time": "-1",
  "target_processing_time": "-1",
  "response_processing_time": "-1",
  "elb_status_code": "200",
  "target_status_code": "-",
  "received_bytes": "128",
  "sent_bytes": "197",
  "request_line": "GET http://alb-cwlogs-test-xxxxxxxxxx.ap-northeast-1.elb.amazonaws.com:80/path5 HTTP/1.1",
  "user_agent": "curl/8.18.0",
  "ssl_cipher": "-",
  "ssl_protocol": "-",
  "target_group_arn": "-",
  "trace_id": "Root=1-6a62d13d-447a49680bbf5e3336d518b3",
  "domain_name": "-",
  "chosen_cert_arn": "-",
  "matched_rule_priority": "0",
  "request_creation_time": "2026-07-24T02:43:09.548000Z",
  "actions_executed": "fixed-response",
  "redirect_url": "-",
  "error_reason": "-",
  "target_port_list": "-",
  "target_status_code_list": "-",
  "classification": "-",
  "classification_reason": "-",
  "conn_trace_id": "TID_ea38a7ed01f3f64b9375d9926c5f7020",
  "transformed_host": "-",
  "transformed_uri": "-",
  "request_transform_status": "-",
  "ip_address": "203.0.113.2"
}

Format Comparison

I output the same requests in three formats and compared their sizes. Note that with the plain format, fields are not automatically parsed, and Logs Insights treats each as a one-line text in @message. Manual parsing is possible with the parse command.

Here is an example of CSV format (comma-delimited) output.

http,2026-07-24T02:48:03.663959Z,app/alb-cwlogs-test/xxxxxxxxxxxxxxxx,203.0.113.1:4985,-,-1,-1,-1,200,-,132,197,"GET http://alb-cwlogs-test-xxxxxxxxxx.ap-northeast-1.elb.amazonaws.com:80/csv-test5 HTTP/1.1","curl/8.18.0",-,-,-,"Root=1-6a62d263-2f7e4aff1e45ff8f0ecb663e","-","-",0,2026-07-24T02:48:03.663000Z,"fixed-response","-","-","-","-","-","-",TID_7e837b9425ba30419301a6a9ba62062f,"-","-","-",203.0.113.3

Here is an example of legacy-compatible format (space-delimited) output.

http 2026-07-24T02:48:03.663959Z app/alb-cwlogs-test/xxxxxxxxxxxxxxxx 203.0.113.1:4985 - -1 -1 -1 200 - 132 197 "GET http://alb-cwlogs-test-xxxxxxxxxx.ap-northeast-1.elb.amazonaws.com:80/csv-test5 HTTP/1.1" "curl/8.18.0" - - - "Root=1-6a62d263-2f7e4aff1e45ff8f0ecb663e" "-" "-" 0 2026-07-24T02:48:03.663000Z "fixed-response" "-" "-" "-" "-" "-" "-" TID_7e837b9425ba30419301a6a9ba62062f "-" "-" "-" 203.0.113.3

Here is a size comparison for 5 records of the same requests.

Format Total bytes Average bytes/record Ratio to JSON
JSON 5,203 bytes 1,041 bytes 100%
CSV (plain, comma) 2,058 bytes 412 bytes 39.6%
Legacy (plain, space) 2,058 bytes 412 bytes 39.6%

CSV and legacy-compatible formats are the same size because both use a one-character delimiter. Due to the overhead of key names, JSON is about 2.53 times the size of plain format. On the other hand, JSON format is superior in query convenience because fields are automatically parsed in Logs Insights.

Delivery Time Lag

To see how long delivery actually takes, I looked at the difference between @timestamp and @ingestionTime. The delivery delay was about 2 to 3 minutes, which was slightly faster than the 5 minutes/file of S3 legacy.

  • @timestamp is automatically mapped from the time field in the JSON, and @ingestionTime is the time of ingestion into CloudWatch Logs
Request time (time) Ingestion time (@ingestionTime) Lag
02:43:09 02:45:06 About 2 min
02:48:03 02:50:05 About 2 min
02:51:51 02:55:06 About 3 min
02:53:00 02:55:06 About 2 min

About Pricing

Delivery charges follow the Vended Logs pricing structure. The unit prices for the Tokyo region as of July 2026 are as follows.

Tier Price
First 10TB/month $0.50/GB
Next 20TB/month $0.25/GB
Next 20TB/month $0.10/GB
Over 50TB/month $0.05/GB

On the other hand, conventional S3 legacy logs are free to deliver, and only S3 storage costs are incurred.

Since plain format requires only about 40% of the data volume of JSON, plain format is advantageous if you want to keep Vended Logs charges down.

A comparison of actual costs, including combination with S3 Parquet conversion and long-term retention, is planned for a follow-up article.

Summary

ALB access logs, connection logs, and health check logs can now be delivered directly to CloudWatch Logs. Because the Vended Logs API starts delivery just by specifying the ALB's ARN, it is also easy to add logging to managed ALBs, such as those created by Amazon ECS Express Mode or Elastic Beanstalk environments. In the follow-up article, I plan to dig deeper into comparisons with the legacy setup, including costs involving S3 Parquet conversion.

https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html

https://aws.amazon.com/cloudwatch/pricing/

Share this article

AWSのお困り事はクラスメソッドへ