DynamoDB Cost Optimization - Device Logs
π΄ The Problem
Current Implementation: Device log Lambda writes EACH log entry individuallyCost Impact
If a device sends 100 logs in a batch, this makes 100 separate DynamoDB write requests. DynamoDB On-Demand Pricing: $1.25 per million write request units (WRUs)| Scenario | Logs/Device/Day | Total Writes/Month | Cost/Month |
|---|---|---|---|
| 1 device, 1 log/min | 1,440 | 43K | $0.054 |
| 1 device, 1 log/sec | 86,400 | 2.6M | $3.24 |
| 5 devices, 1 log/sec | 432,000 | 13M | $16.20 |
| 50 devices, 1 log/sec | 4.3M | 130M | $162.00 |
β The Solution: Batch Writes
Use DynamoDBβsbatch_write_item() API to write up to 25 items per request.
New Implementation
Cost Savings
| Scenario | Old Writes | New Writes (Γ·25) | Old Cost | New Cost | Savings |
|---|---|---|---|---|---|
| 5 devices @ 1 log/sec | 13M | 520K | $16.20 | $0.65 | $15.55 (96%) β |
| 50 devices @ 1 log/sec | 130M | 5.2M | $162.00 | $6.50 | $155.50 (96%) β |
Updated Plan Costs
Free Plan
| Resource | Old Cost | New Cost | Savings |
|---|---|---|---|
| DynamoDB Logs | $1.32 | $0.053 | $1.27 (96%) |
| Other | $0.43 | $0.43 | - |
| Total | $1.75 | $0.48 | $1.27 β |
Personal Plan ($29/month)
| Resource | Old Cost | New Cost | Savings |
|---|---|---|---|
| DynamoDB Logs | $6.60 | $0.26 | $6.34 (96%) |
| Other | $1.46 | $1.46 | - |
| Total | $8.06 | $1.72 | $6.34 β |
Team Plan ($99/month)
| Resource | Old Cost | New Cost | Savings |
|---|---|---|---|
| DynamoDB Logs | $66.00 | $2.64 | $63.36 (96%) |
| Other | $12.10 | $12.10 | - |
| Total | $78.10 | $14.74 | $63.36 β |
Real-World Impact
Scenario: 20 Personal + 10 Team Users
Before Optimization:- Fixed Costs: $116.63
- Variable Costs: (20 Γ 78.10) = $942.20
- Revenue: $1,570
- Net Profit: $511.17 (32.6% margin)
- Fixed Costs: $116.63
- Variable Costs: (20 Γ 14.74) = $181.80
- Revenue: $1,570
- Net Profit: $1,271.57 (81% margin) π
Implementation Details
Key Changes to device-logs/index.py
-
Added
_convert_to_dynamodb_item()helper (Lines 26-68)- Converts Python types to DynamoDB format (S, N, M, L types)
- Required for
batch_write_itemAPI
-
Replaced individual writes with batch writes (Lines 79-128)
- Collects all items first
- Writes in chunks of 25 (DynamoDB limit)
- Handles unprocessed items with retry
- Falls back to individual writes on error
Error Handling
- If batch write fails, automatically retries unprocessed items
- If retry fails, falls back to individual
put_item()for that batch - Ensures no log data is lost
Testing Recommendations
- Test with small batch (1-5 logs): Verify single batch write works
- Test with large batch (50+ logs): Verify chunking into multiple batches
- Test with invalid data: Verify fallback to individual writes
- Monitor CloudWatch logs: Check for any batch write errors
Additional Optimization Ideas
1. Log Sampling for Free Users
Only write every 10th log for free users:2. Aggregate Logs Before Writing
Combine multiple logs into a single item:3. Time-based Buffering
Buffer logs for 5 minutes, then write in one batch:- Use SQS to queue logs
- Lambda processes queue every 5 minutes
- Savings: Reduce Lambda invocations + more efficient batching
4. Use S3 for Log Archive, DynamoDB for Recent Only
- Write last 24 hours to DynamoDB (queryable)
- Archive older logs to S3 (cheap storage)
- Use DynamoDB TTL (already configured)
- Savings: ~50% DynamoDB storage costs
Cost Summary
| Metric | Before | After | Improvement |
|---|---|---|---|
| Free Plan Loss | -$1.75/user | -$0.48/user | 73% better |
| Personal Margin | 72% | 94% | +22 pp |
| Team Margin | 21% β | 85% β | +64 pp |
| 20P+10T Profit | $511 | $1,271 | +149% |
Deployment
The fix has been applied to:/infrastructure/lambda/device-logs/index.py
- Test locally or in staging environment
- Deploy with
cdk deploy - Monitor CloudWatch logs for any batch write errors
- Check DynamoDB metrics to confirm 25x reduction in writes