Cost-Effective Audit Logging for Amazon RDS: A Practical AWS Architecture
Amazon RDS | AWS | MySQL | CloudWatch | S3 | Athena | Grafana | Cost Optimization
Database auditing is one of those things that often gets added to an AWS environment after a security or compliance requirement appears.
At first, the solution looks simple:
Enable RDS audit logs → send them to CloudWatch → keep them forever.
Technically, this works.
Financially, however, it can become expensive very quickly—especially when you start logging every SQL query, including millions of SELECT, INSERT, UPDATE, and application-generated queries every day.
A better approach is to design RDS auditing around what you actually need to audit, rather than logging everything.
This article explains how to build a cost-effective audit logging architecture for Amazon RDS for MySQL, while still maintaining useful security, operational, and compliance visibility.
The core idea is:
Generate only the audit events you need, keep short-term logs in CloudWatch when real-time investigation is required, and use Amazon S3 for inexpensive long-term retention.
1. Why RDS Audit Logging Can Become Expensive
Consider a production application running on Amazon RDS for MySQL.
Every day, the application might execute:
- Thousands of authentication events
- Millions of
SELECTqueries - Hundreds of thousands of
INSERToperations - Hundreds of thousands of
UPDATEoperations - Database schema changes
- Background jobs
- Health checks
- ORM-generated queries
- Monitoring queries
- Replication-related activity
If we enable unrestricted SQL auditing, the database can generate a huge amount of log data.
That creates three separate costs:
- Database performance overhead
- Log ingestion cost
- Log storage and retention cost
The important point is that these costs are not necessarily required.
For many environments, you don't need to know every SELECT statement that an application executes.
You may only need to know:
- Who connected?
- Did authentication fail?
- Who changed the database schema?
- Who executed
DROP TABLE? - Who modified privileges?
- Which application or IP connected to the database?
That is where selective auditing becomes useful.
2. The Basic Architecture
A cost-effective architecture separates the problem into two stages:
Amazon RDS for MySQL
|
|
Audit Plugin
|
v
Local Audit Log
/rdsdbdata/log/audit/
server_audit.log
|
+----------+----------+
| |
v v
CloudWatch Logs S3 Archive
| |
| |
v v
Real-Time Search Long-Term Storage
| |
v v
Alerts / SOC Athena / Grafana
The architecture has two important responsibilities:
Step 1 — Generate audit events
The MySQL engine needs to actually generate the audit events.
For RDS MySQL, the provided architecture uses the AWS-supported MariaDB Audit Plugin through an RDS option group.
The plugin writes audit information to the local RDS audit log.
Step 2 — Export and retain the logs
Once audit events are generated, they can be routed externally.
Two approaches are possible:
- RDS → CloudWatch Logs
- RDS → scheduled retrieval → S3
The first is simpler and provides near-real-time visibility.
The second can significantly reduce ingestion costs when dealing with large audit volumes.
The supplied architecture describes these two stages explicitly: audit generation through MARIADB_AUDIT_PLUGIN, followed by log export through the RDS Audit Log export setting.
3. Why the Audit Plugin Matters
One common mistake is to enable:
RDS → Log exports → Audit log
and assume audit logging is now working.
It isn't necessarily enough.
The database engine must first generate audit events.
The architecture therefore uses:
RDS Option Group
|
v
MARIADB_AUDIT_PLUGIN
|
v
server_audit.log
|
v
CloudWatch Logs
The audit plugin is responsible for generating the audit information, while the RDS log-export mechanism is responsible for shipping it.
The specification also highlights an important operational trap: enabling the CloudWatch audit export without configuring the audit plugin can result in a CloudWatch log group that exists but contains no audit events.
4. The Three Audit Logging Levels
One of the most important decisions is deciding how much SQL activity should actually be logged.
A useful way to think about this is to create three audit tiers.
Tier 1
Selective
↓
Authentication + DDL
Tier 2
Moderate
↓
Authentication + DDL + DML
Tier 3
Unfiltered
↓
Everything
The more you log, the more you pay—in storage, ingestion, processing, and potentially database performance.
5. Tier 1 — Selective Auditing
For most production environments, the first question should be:
Do we really need every database query?
Usually, the answer is no.
A selective audit configuration focuses on security-sensitive events.
Example:
SERVER_AUDIT_EVENTS = CONNECT,QUERY_DDL
You can also exclude infrastructure and monitoring accounts:
SERVER_AUDIT_EXCL_USERS = rdsadmin, datadog_agent, healthcheck_user, replication_user
And control the query log size:
SERVER_AUDIT_QUERY_LOG_LIMIT = 1024
This captures events such as:
Authentication
CONNECT
Useful information includes:
- User
- Source IP
- Timestamp
- Successful connections
- Failed authentication attempts
- Disconnect events
For security investigations, this information can be much more useful than millions of routine SELECT statements.
Schema changes
QUERY_DDL
This captures operations such as:
CREATE TABLE ALTER TABLE DROP TABLE TRUNCATE TABLE RENAME TABLE
For example:
DROP TABLE customers;
An audit trail showing:
User: application_admin Source IP: 10.20.5.12 Timestamp: 2026-09-21 10:32:11 Statement: DROP TABLE customers
can be extremely valuable during an incident.
The supplied architecture estimates Tier 1 at approximately 1–5 GB/day, compared with dramatically larger volumes for broader auditing.
6. Tier 2 — Moderate Auditing
Some organizations need to know when data is changed.
In that case, authentication and DDL events aren't enough.
You may also need:
QUERY_DML_NO_SELECT
This adds operations such as:
INSERT UPDATE DELETE REPLACE
The resulting configuration becomes:
CONNECT + QUERY_DDL + QUERY_DML_NO_SELECT
Notice what is intentionally missing:
SELECT
This is an important optimization.
Suppose your application executes:
SELECT * FROM customers WHERE id = 123;
millions of times per day.
Logging every one of those queries can produce enormous audit volumes.
Instead, you can focus on mutations:
UPDATE customers SET email = 'new@example.com' WHERE id = 123;
This provides a much stronger audit trail for environments where data modification matters.
The supplied design estimates Tier 2 at roughly 15–50 GB/day, with greater CPU and I/O overhead than selective auditing.
7. Tier 3 — Unfiltered Auditing
The third approach is:
Log everything.
For example:
SERVER_AUDIT_EVENTS = CONNECT,QUERY
This means you may capture:
SELECT INSERT UPDATE DELETE CREATE ALTER DROP
as well as application health checks and other routine database traffic.
At first glance, this sounds like the most secure approach.
But more logging does not automatically mean better security.
There are several problems.
Problem 1 — Huge log volumes
A busy production application could generate enormous audit logs.
The architecture estimates approximately:
100–1,000+ GB/day
for this type of unrestricted auditing.
Problem 2 — Cost
If these logs are continuously pushed into CloudWatch, ingestion charges can become significant.
Problem 3 — Performance
The more queries the database has to audit, the greater the processing overhead.
Problem 4 — Sensitive information
SQL statements can contain sensitive information.
For example:
INSERT INTO users
(name, email, token)
VALUES
('John', 'john@example.com', 'secret-token');
If the entire statement is logged, sensitive values may end up in the audit system.
That means audit logging itself needs security controls.
8. Audit Tier Comparison
FeatureTier 1: SelectiveTier 2: ModerateTier 3: UnfilteredAuthenticationYesYesYesFailed loginsYesYesYesDDLYesYesYesINSERT/UPDATE/DELETENoYesYesSELECTNoNoYesApprox. daily volume1–5 GB15–50 GB100–1,000+ GBCPU overheadLowModerateHighStorage pressureLowModerateHighOperational complexityLowModerateHighTypical useSecurity/complianceData mutation auditingDeep forensic investigation
The important lesson is:
Choose the smallest audit scope that satisfies your actual security and compliance requirements.
The source specification similarly separates these tiers based on logged events, volume, cost, CPU overhead, and compliance use cases.
9. CloudWatch vs S3
Once you decide what to log, the next question is:
Where should those logs live?
Two common choices are:
Option A
RDS ↓ CloudWatch Logs
Option B
RDS ↓ Audit Logs ↓ S3
They solve slightly different problems.
10. CloudWatch: The Easy Option
CloudWatch is attractive because AWS manages the entire streaming process.
You enable:
RDS → Modify → Log exports → Audit log
The audit log is then exported into a CloudWatch log group similar to:
/aws/rds/instance/<db-name>/audit
This provides:
- Near-real-time logs
- CloudWatch Logs Insights
- Metric filters
- Alarms
- Easy integration with AWS monitoring
- Minimal infrastructure to maintain
The supplied architecture describes CloudWatch as the simplest operational path, with logs becoming available in roughly 30–60 seconds.
11. The Problem With Keeping Everything in CloudWatch
CloudWatch is excellent for short-term operational investigation.
It isn't always the most economical place for long-term archival.
Imagine:
5 GB/day
That becomes approximately:
150 GB/month
And:
1 year ≈ 1.8 TB
Now imagine a Tier 2 or Tier 3 workload.
The numbers become much larger.
This is why retention policies matter.
A common architecture is:
RDS ↓ CloudWatch ↓ 7-day retention ↓ S3 ↓ Glacier lifecycle
CloudWatch handles your immediate operational needs.
S3 handles your long-term retention.
The supplied design specifically recommends short CloudWatch retention rather than leaving logs indefinitely in CloudWatch.
12. S3 for Long-Term Audit Storage
Amazon S3 is a natural destination for long-term audit archives.
A possible structure is:
s3://company-audit-logs/
rds/
production/
mysql/
2026/
09/
21/
audit-001.gz
audit-002.gz
This makes the data easier to partition by:
- Environment
- Database
- Year
- Month
- Day
You can then apply S3 Lifecycle policies.
For example:
Day 0–30
S3 Standard
Day 30–90
S3 Glacier Instant Retrieval
Day 90+
Glacier Deep Archive
The exact lifecycle should depend on your compliance and investigation requirements.
13. Two Ways to Get RDS Audit Logs Into S3
There are two architectural approaches.
Approach 1 — CloudWatch First
RDS ↓ CloudWatch Logs ↓ Export/archive ↓ S3
This is simpler operationally.
The downside is that the logs first incur CloudWatch ingestion.
Approach 2 — Scheduled Lambda
The architecture you provided also describes a more cost-focused design:
RDS ↓ DownloadDBLogFilePortion ↓ Lambda ↓ gzip ↓ S3
A typical implementation uses:
EventBridge
|
v
Lambda
|
+----> RDS API
|
+----> DynamoDB
|
v
S3
EventBridge
Triggers the Lambda periodically.
For example:
Every 10–15 minutes
Lambda
Retrieves new portions of the audit log.
DynamoDB
Stores state so Lambda knows which portion of the log has already been processed.
S3
Stores compressed audit files.
The supplied design identifies this as a way to bypass CloudWatch ingestion entirely, although it also notes the additional operational complexity and the possibility of log-pruning risk if polling cannot keep up with log rotation.
14. CloudWatch vs Lambda-to-S3
AreaCloudWatchLambda → S3SetupVery simpleMore complexReal-timeYesNoCloudWatch ingestionYesNoLong-term storageExpensiveCheapSearchLogs InsightsAthenaMaintenanceMinimalRequires maintenanceFailure pointsFewMoreBest useOperational monitoringHigh-volume archival
The important architectural point is:
Don't optimize for storage cost at the expense of operational reliability.
If you only generate 1–5 GB/day, CloudWatch may be perfectly reasonable.
If your audit volume becomes tens or hundreds of GB per day, direct S3 archival becomes much more attractive.
15. A Practical Hybrid Architecture
For most production systems, a hybrid architecture is easier to operate:
┌──────────────────────┐
│ Amazon RDS MySQL │
└──────────┬───────────┘
│
MariaDB Audit Plugin
│
v
Audit Log Generation
│
┌────────────┴────────────┐
│ │
v v
CloudWatch Logs S3
7-day retention Long-term archive
│ │
│ │
v v
Alerts / Logs Athena Queries
Insights │
v
Grafana
This architecture gives you:
Short-term visibility
CloudWatch provides fast investigation.
Long-term retention
S3 provides inexpensive storage.
Analytics
Athena lets you query archived logs.
Dashboards
Grafana can visualize the audit information.
16. Cost Optimization Doesn't Mean "Use the Cheapest Service"
This is an important DevOps lesson.
Suppose you have two options:
Option A
CloudWatch $X/month
Option B
Lambda + EventBridge + DynamoDB + S3 + Athena
Option B may have lower raw ingestion costs.
But it also has:
- More infrastructure
- More IAM permissions
- More failure scenarios
- More monitoring
- More code
- More maintenance
Therefore:
Total cost of ownership matters more than the price of a single AWS service.
For a low-volume audit workload, CloudWatch may be the better engineering decision even if S3 storage is cheaper.
For a high-volume audit workload, the additional architecture may justify itself.
17. CloudWatch Retention Strategy
One of the easiest cost optimizations is simply configuring log retention.
Avoid:
Retention = Never Expire
unless there is a specific reason.
Instead, consider:
CloudWatch
|
+-- 7 days
and:
S3
|
+-- 30 days Standard
+-- 90 days Glacier
+-- Long-term Deep Archive
This creates a clear separation:
Hot data ↓ CloudWatch Warm / archive data ↓ S3 Cold compliance data ↓ Glacier
18. Querying Archived Logs With Athena
Once audit logs are in S3, you don't necessarily need to move them back into CloudWatch.
You can use:
Amazon Athena
to query them.
Architecture:
S3 ↓ Athena ↓ SQL
For example, conceptually:
SELECT
event_time,
user,
host,
command
FROM rds_audit_logs
WHERE event_type = 'QUERY_DDL'
AND event_date = '2026-09-21';
You can investigate questions such as:
- Who changed the schema?
- When did the change occur?
- Which database user performed it?
- What client connected?
- How many failed login attempts occurred?
- Which source IP generated the connections?
19. Athena + Grafana
If your organization already operates Grafana, you can build a lightweight audit dashboard.
Architecture:
S3 ↓ Athena ↓ Grafana
Possible dashboard panels:
Authentication
Successful logins Failed logins Unique users Unique source IPs
DDL
CREATE ALTER DROP TRUNCATE
Top users
User Number of connections Number of changes
Source IPs
IP address Connection count Failed login count
Timeline
Audit events over time
The supplied design estimates the Athena + Grafana approach at approximately $5–$15/month, depending on usage and the existing Grafana infrastructure.
20. Athena + QuickSight
Another option is:
S3 ↓ Athena ↓ Amazon QuickSight
This is attractive when the organization already uses AWS-native BI tooling.
It can provide:
- Managed dashboards
- Scheduled reports
- Visualizations
- External reporting
The supplied architecture estimates approximately $25–$55/month for the described setup, depending on the QuickSight configuration and usage.
21. Alerting: Don't Just Store Logs
Audit logging is much more useful when important events generate alerts.
For example:
Audit Log
|
v
Detection
|
v
Alert
|
v
Slack / PagerDuty / Security Team
Useful alerts include:
Multiple failed logins
Example threshold:
> 5 failures within 5 minutes
This can identify potential brute-force activity.
Production schema changes
Alert on:
DROP TABLE ALTER TABLE TRUNCATE TABLE
These events can have significant operational impact.
Unexpected source IP
If production RDS should only receive traffic from:
VPC application subnets VPN Bastion Private connectivity
then connections from unexpected locations deserve investigation.
The supplied design proposes these three categories as examples of high-severity audit alerts.
22. Don't Alert on Everything
A common monitoring mistake is creating too many alerts.
For example:
Every SELECT Every INSERT Every connection Every successful login
can create alert fatigue.
Instead, focus alerts on events that require human attention.
For example:
Failed authentication spike
↓
Alert
DROP TABLE in production
↓
Alert
Unexpected source IP
↓
Alert
While normal events can simply be retained:
Successful connection
↓
Store
Normal application query
↓
Do not audit / store based on policy
23. Security Controls for Audit Logs
Audit logs themselves contain sensitive information.
Therefore, protect them like production data.
Encrypt the logs
Use AWS KMS where appropriate.
For S3:
S3 ↓ SSE-KMS
For CloudWatch:
CloudWatch Log Group ↓ KMS
The architecture recommends KMS-based encryption for both CloudWatch and S3 storage.
24. Restrict Access
Not every engineer needs access to audit logs.
A reasonable model is:
Developers ↓ No direct audit access DevOps ↓ Operational access Security / Compliance ↓ Full audit access
Use IAM policies to control:
- CloudWatch Logs access
- S3 access
- Athena access
- KMS decrypt permissions
For particularly sensitive audit archives, consider additional S3 controls such as:
Bucket policies Block Public Access Versioning Object Lock KMS CloudTrail monitoring
25. Protect Against Audit Log Tampering
An audit system is only useful if attackers cannot easily modify the evidence.
A strong architecture separates:
Production AWS Account
|
v
Audit Log Bucket
|
v
Restricted Security Account
For higher-security environments, consider centralized logging into a dedicated security/logging account.
The goal is to prevent someone who compromises the application environment from simply deleting the audit evidence.
26. Cost Optimization Checklist
Here is the practical checklist I would use when designing RDS audit logging.
1. Don't automatically log every query
Start with:
CONNECT + QUERY_DDL
and expand only when there is a documented requirement.
2. Exclude noisy service accounts
Exclude accounts such as:
healthcheck monitoring replication
when they do not provide useful audit information.
3. Avoid logging SELECT unless required
SELECT traffic can dominate audit volume.
4. Use CloudWatch for short-term visibility
For example:
7 days
5. Use S3 for long-term retention
Apply lifecycle policies.
6. Compress archived logs
Use:
gzip
before long-term storage.
7. Use Athena for historical investigations
Don't keep every historical log in CloudWatch just because you might need it someday.
8. Reuse existing Grafana infrastructure
If your organization already has Grafana, Athena + Grafana can avoid introducing another dashboard platform.
9. Monitor the audit pipeline
If you use Lambda:
Lambda Errors Lambda Duration Lambda Invocations DynamoDB Errors S3 Upload Failures RDS API failures
should be monitored.
10. Review audit requirements periodically
Don't let an audit configuration become permanent simply because someone enabled it years ago.
27. Example Production Architecture
A practical production architecture could look like this:
┌─────────────────────┐
│ Application │
└──────────┬──────────┘
│
v
┌─────────────────────┐
│ Amazon RDS MySQL │
└──────────┬──────────┘
│
Audit Plugin
│
v
┌─────────────────────┐
│ Audit Log Generator │
└──────────┬──────────┘
│
┌────────────────┴────────────────┐
│ │
v v
┌──────────────────┐ ┌─────────────────┐
│ CloudWatch Logs │ │ S3 │
│ 7-day retention │ │ Long-term logs │
└────────┬─────────┘ └────────┬────────┘
│ │
v v
┌──────────────────┐ ┌─────────────────┐
│ Logs Insights │ │ Athena │
└────────┬─────────┘ └────────┬────────┘
│ │
v v
┌──────────────────┐ ┌─────────────────┐
│ CloudWatch │ │ Grafana / BI │
│ Alerts │ │ Dashboard │
└────────┬─────────┘ └─────────────────┘
│
v
┌──────────────────┐
│ Slack / PagerDuty│
│ Security Team │
└──────────────────┘
This gives you three layers:
Layer 1 — Detection
CloudWatch + alerts.
Layer 2 — Investigation
CloudWatch Logs Insights.
Layer 3 — Historical audit
S3 + Athena + Grafana.
28. A Cost-Effective Strategy by Audit Volume
You can simplify the decision using the following model.
Low-volume audit
1–5 GB/day
Use:
RDS ↓ CloudWatch ↓ 7-day retention ↓ S3 archive
The additional operational simplicity is valuable.
Medium-volume audit
15–50 GB/day
Consider:
RDS ↓ CloudWatch for short-term + S3 for archive
and evaluate whether direct S3 ingestion is justified.
High-volume audit
100+ GB/day
Strongly consider:
RDS ↓ Audit logs ↓ S3 ↓ Athena ↓ Grafana
while using CloudWatch only for the events that actually require real-time monitoring.
This avoids paying to ingest huge amounts of historical audit data into a hot log analytics system.
29. The Most Important Design Principle
The most important lesson isn't:
"Use S3 because it's cheaper."
It is:
Design the audit scope first, then choose the storage and analytics architecture.
For example:
Requirement
↓
What events must be audited?
↓
How much data will that generate?
↓
Does it require real-time investigation?
↓
How long must it be retained?
↓
Where should it be stored?
↓
How should it be queried?
↓
What should generate alerts?
This prevents over-engineering.
30. Recommended Reference Architecture
For a typical AWS production environment, a practical design is:
AUDIT GENERATION
|
v
MARIADB_AUDIT_PLUGIN
|
+-------------------------+
| |
v v
CONNECT + DDL DML if required
| |
+------------+------------+
|
v
Audit Logs
|
+---------+---------+
| |
v v
CloudWatch S3
7-day TTL Long-term archive
| |
v v
Alerts Athena
|
v
Grafana
Start with selective auditing.
Expand only when a real requirement exists.
31. Final Takeaway
RDS audit logging doesn't have to become an expensive logging project.
The biggest cost optimization is actually made before the log reaches CloudWatch or S3.
If you generate unnecessary logs, no storage architecture can completely solve the problem.
A better strategy is:
1. Audit only meaningful events
↓
2. Exclude noisy service accounts
↓
3. Avoid SELECT auditing unless required
↓
4. Use CloudWatch for short-term investigation
↓
5. Use S3 for long-term retention
↓
6. Compress and lifecycle archived logs
↓
7. Use Athena for historical analysis
↓
8. Use Grafana/QuickSight for dashboards
↓
9. Alert only on high-value security events
For many environments, selective auditing + short CloudWatch retention + S3 archival provides a good balance between security visibility, operational simplicity, and cost.
For high-volume audit requirements, a more direct RDS → S3 → Athena → Grafana architecture can reduce CloudWatch ingestion costs, but it introduces additional components and operational responsibilities.
The right architecture is therefore not simply the cheapest one.
It is the one that gives your organization the required audit evidence with the lowest practical operational and financial overhead.
Quick Reference
RequirementRecommended ApproachAuthentication auditingCONNECTSchema-change auditingQUERY_DDLData-change auditingQUERY_DML_NO_SELECTAvoid excessive volumeDon't audit SELECT unless requiredReal-time investigationCloudWatch LogsShort-term retentionCloudWatchLong-term retentionS3Cold archivalS3 Glacier classesHistorical SQL analysisAthenaExisting Grafana environmentAthena + GrafanaAWS-native BIAthena + QuickSightHigh-volume auditPrefer S3-centric architectureLow-volume auditCloudWatch + S3 hybridSecurityKMS + IAM + private S3 + restricted accessAlertingFailed logins, production DDL, unexpected sources
The goal of audit logging is not to collect the maximum amount of data. The goal is to collect the right evidence, retain it securely, and make it available when you actually need it.