Skip to content

Commit 00d6025

Browse files
committed
specs: migrate to aws sdk v3
1 parent b3e1c84 commit 00d6025

File tree

3 files changed

+531
-0
lines changed

3 files changed

+531
-0
lines changed
Lines changed: 360 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,360 @@
1+
# Design Document
2+
3+
## Overview
4+
5+
This design document outlines the migration strategy for transitioning the notifyer-cron serverless application from AWS SDK for JavaScript v2 to v3. The migration focuses on maintaining functional equivalence while leveraging v3's performance improvements, reduced bundle sizes, and modular architecture.
6+
7+
The primary changes involve replacing the v2 `AWS.DynamoDB.DocumentClient` with v3's modular `@aws-sdk/client-dynamodb` and `@aws-sdk/lib-dynamodb` packages, updating import statements, client instantiation patterns, and error handling to align with v3's architecture.
8+
9+
## Architecture
10+
11+
### Current Architecture (v2)
12+
```
13+
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
14+
│ Lambda │ │ AWS SDK v2 │ │ DynamoDB │
15+
│ Functions │───▶│ DocumentClient │───▶│ Table │
16+
│ │ │ (93.6MB) │ │ │
17+
└─────────────────┘ └──────────────────┘ └─────────────────┘
18+
```
19+
20+
### Target Architecture (v3)
21+
```
22+
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
23+
│ Lambda │ │ AWS SDK v3 │ │ DynamoDB │
24+
│ Functions │───▶│ Modular Client │───▶│ Table │
25+
│ │ │ (17MB) │ │ │
26+
└─────────────────┘ └──────────────────┘ └─────────────────┘
27+
28+
├─ @aws-sdk/client-dynamodb
29+
└─ @aws-sdk/lib-dynamodb
30+
```
31+
32+
### Migration Strategy
33+
The migration will follow a **direct replacement approach** rather than gradual migration, ensuring:
34+
- Single deployment with complete v3 implementation
35+
- Minimal code changes through strategic abstraction
36+
- Preservation of existing functionality and error handling patterns
37+
- Optimization for serverless/Lambda environment
38+
39+
## Components and Interfaces
40+
41+
### 1. Database Persistence Layer (`db/persist.js`)
42+
43+
**Current Implementation:**
44+
```javascript
45+
const AWS = require('aws-sdk')
46+
const documentClient = new AWS.DynamoDB.DocumentClient({
47+
apiVersion: '2012-10-08'
48+
})
49+
```
50+
51+
**Target Implementation:**
52+
```javascript
53+
const { DynamoDBClient } = require('@aws-sdk/client-dynamodb')
54+
const { DynamoDBDocumentClient, GetCommand, UpdateCommand } = require('@aws-sdk/lib-dynamodb')
55+
56+
const client = new DynamoDBClient({
57+
region: process.env.REGION
58+
})
59+
60+
const documentClient = DynamoDBDocumentClient.from(client, {
61+
marshallOptions: {
62+
removeUndefinedValues: true // Maintain v2 behavior
63+
}
64+
})
65+
```
66+
67+
**Interface Changes:**
68+
- Replace `.promise()` calls with direct `await` on `send()` method
69+
- Update error handling to account for v3's error structure (`error.$metadata`)
70+
- Maintain existing `getItem()` and `setItem()` function signatures
71+
72+
### 2. Package Dependencies
73+
74+
**Removals:**
75+
- `aws-sdk` (v2) from devDependencies
76+
77+
**Additions:**
78+
- `@aws-sdk/client-dynamodb` (v3)
79+
- `@aws-sdk/lib-dynamodb` (v3)
80+
81+
**Bundle Size Impact:**
82+
- Current: ~93.6MB install size
83+
- Target: ~17MB install size
84+
- Runtime bundle reduction: ~3.4MB → ~234KB
85+
86+
### 3. Serverless Plugin Compatibility
87+
88+
**Current Plugins:**
89+
- `serverless-webpack` (v5.11.0)
90+
- `serverless-offline` (v12.0.4)
91+
- `serverless-dynamodb-local` (v0.2.40) - currently commented out
92+
93+
**Compatibility Assessment:**
94+
- **serverless-webpack**: Generally compatible with v3, may need version verification
95+
- **serverless-offline**: Should work with v3 SDK operations, requires testing
96+
- **serverless-dynamodb-local**: May need updates for v3 compatibility if re-enabled
97+
98+
**Webpack Configuration:**
99+
```javascript
100+
// webpack.config.js - current configuration maintained
101+
module.exports = {
102+
externals: {
103+
// AWS SDK v3 modules will be bundled for optimal tree-shaking
104+
// No externals needed as v3 is designed for bundling
105+
}
106+
}
107+
```
108+
109+
**Serverless Framework Integration:**
110+
- Maintain existing `serverless-webpack` plugin configuration
111+
- Leverage v3's improved tree-shaking for smaller bundles
112+
- No changes required to `serverless.yml`
113+
- Verify plugin compatibility and upgrade if necessary
114+
115+
**Plugin Compatibility Research Required:**
116+
- Verify serverless-webpack v5.11.0 works with AWS SDK v3 modular imports
117+
- Test serverless-offline v12.0.4 compatibility with v3 SDK operations
118+
- Check if serverless-dynamodb-local v0.2.40 needs updates for v3 (if re-enabled)
119+
- Document any required plugin version upgrades or configuration changes
120+
121+
## Data Models
122+
123+
### DynamoDB Operations Mapping
124+
125+
| Operation | v2 Implementation | v3 Implementation |
126+
|-----------|-------------------|-------------------|
127+
| Get Item | `documentClient.get(params).promise()` | `documentClient.send(new GetCommand(params))` |
128+
| Update Item | `documentClient.update(params).promise()` | `documentClient.send(new UpdateCommand(params))` |
129+
130+
### Error Structure Changes
131+
132+
**v2 Error Structure:**
133+
```javascript
134+
{
135+
code: 'ResourceNotFoundException',
136+
statusCode: 400,
137+
// ... other top-level properties
138+
}
139+
```
140+
141+
**v3 Error Structure:**
142+
```javascript
143+
{
144+
name: 'ResourceNotFoundException',
145+
$metadata: {
146+
httpStatusCode: 400,
147+
// ... metadata in subfield
148+
}
149+
}
150+
```
151+
152+
### Data Marshalling Considerations
153+
154+
**Key Configuration:**
155+
```javascript
156+
const documentClient = DynamoDBDocumentClient.from(client, {
157+
marshallOptions: {
158+
removeUndefinedValues: true, // Replicate v2 behavior
159+
convertEmptyValues: false // Maintain current handling
160+
}
161+
})
162+
```
163+
164+
## Error Handling
165+
166+
### Error Handling Strategy
167+
168+
1. **Preserve Existing Patterns:** Maintain current try/catch blocks and error propagation
169+
2. **Adapt Error Structure:** Update error property access to use v3's structure
170+
3. **Logging Consistency:** Ensure error logs maintain current format
171+
172+
### Implementation Approach
173+
174+
**Current Error Handling:**
175+
```javascript
176+
try {
177+
const data = await documentClient.get(params).promise()
178+
return parse ? JSON.parse(data.Item[itemName]) : data.Item[itemName]
179+
} catch (err) {
180+
console.error(`Error getting db item: '${itemName}'`)
181+
console.error(err)
182+
throw err
183+
}
184+
```
185+
186+
**Target Error Handling:**
187+
```javascript
188+
try {
189+
const data = await documentClient.send(new GetCommand(params))
190+
return parse ? JSON.parse(data.Item[itemName]) : data.Item[itemName]
191+
} catch (err) {
192+
console.error(`Error getting db item: '${itemName}'`)
193+
console.error(err)
194+
throw err // Error structure will be v3 format but handling remains the same
195+
}
196+
```
197+
198+
### Error Compatibility Layer
199+
200+
No compatibility layer needed as:
201+
- Error throwing/catching patterns remain unchanged
202+
- Console logging will work with v3 error objects
203+
- Application-level error handling doesn't depend on specific error properties
204+
205+
## Testing Strategy
206+
207+
### Unit Testing Approach
208+
209+
1. **Functional Equivalence Testing:**
210+
- Test all DynamoDB operations return identical results
211+
- Verify error scenarios produce equivalent behavior
212+
- Validate data marshalling/unmarshalling consistency
213+
214+
2. **Integration Testing:**
215+
- Test complete Lambda function execution
216+
- Verify serverless deployment process
217+
- Test local development with serverless-offline
218+
- Validate AWS IAM permissions compatibility
219+
- Test serverless plugin functionality
220+
221+
3. **Performance Testing:**
222+
- Measure cold start time improvements
223+
- Validate bundle size reductions
224+
- Monitor memory usage changes
225+
226+
### Test Implementation Strategy
227+
228+
**Mock Testing:**
229+
```javascript
230+
// Use aws-sdk-client-mock for v3 testing
231+
const { mockClient } = require('aws-sdk-client-mock')
232+
const { DynamoDBDocumentClient, GetCommand } = require('@aws-sdk/lib-dynamodb')
233+
234+
const ddbMock = mockClient(DynamoDBDocumentClient)
235+
ddbMock.on(GetCommand).resolves({ Item: { test: 'data' } })
236+
```
237+
238+
**Deployment Testing:**
239+
1. Deploy to development environment
240+
2. Execute full application workflow
241+
3. Verify data persistence and retrieval
242+
4. Confirm monitoring and logging functionality
243+
244+
### Rollback Strategy
245+
246+
**Immediate Rollback Capability:**
247+
- Maintain v2 implementation in version control
248+
- Prepare rollback deployment package
249+
- Document rollback procedure
250+
251+
**Rollback Triggers:**
252+
- Functional regression detected
253+
- Performance degradation beyond acceptable thresholds
254+
- Deployment failures in production environment
255+
256+
## Performance Considerations
257+
258+
### Bundle Size Optimization
259+
260+
**Tree-Shaking Benefits:**
261+
- v3's modular architecture enables automatic dead code elimination
262+
- Only required DynamoDB operations will be included in bundle
263+
- Estimated 85% reduction in AWS SDK bundle size
264+
265+
**Cold Start Improvements:**
266+
- Smaller bundle size reduces Lambda initialization time
267+
- Modular imports reduce memory footprint
268+
- Estimated 10-30% improvement in cold start performance
269+
270+
### Memory Usage
271+
272+
**v2 vs v3 Memory Profile:**
273+
- v2: Loads entire AWS SDK into memory
274+
- v3: Loads only required service clients
275+
- Expected memory usage reduction: 20-40%
276+
277+
### Runtime Performance
278+
279+
**Operation Performance:**
280+
- DynamoDB operations: Equivalent performance expected
281+
- Client initialization: Slightly faster due to reduced overhead
282+
- Error handling: Minimal performance impact
283+
284+
## Deployment Strategy
285+
286+
### Deployment Approach
287+
288+
**Single-Phase Deployment:**
289+
1. Research and verify serverless plugin compatibility
290+
2. Update package.json dependencies (including plugin upgrades if needed)
291+
3. Modify db/persist.js implementation
292+
4. Test local development workflow with plugins
293+
5. Deploy complete application
294+
6. Monitor for issues
295+
7. Rollback if necessary
296+
297+
### Deployment Validation
298+
299+
**Pre-Deployment Checklist:**
300+
- [ ] Serverless plugin compatibility verified
301+
- [ ] Unit tests pass
302+
- [ ] Integration tests pass
303+
- [ ] Local development workflow tested (serverless-offline, etc.)
304+
- [ ] Bundle size verification
305+
- [ ] Serverless configuration validation
306+
307+
**Post-Deployment Verification:**
308+
- [ ] Lambda functions execute successfully
309+
- [ ] DynamoDB operations function correctly
310+
- [ ] Error handling works as expected
311+
- [ ] Performance metrics within acceptable ranges
312+
- [ ] Monitoring and logging operational
313+
314+
### Risk Mitigation
315+
316+
**Low-Risk Factors:**
317+
- Minimal code changes required
318+
- Well-documented migration path
319+
- Extensive AWS documentation and community support
320+
- Backward-compatible error handling approach
321+
322+
**Risk Mitigation Measures:**
323+
- Comprehensive testing in development environment
324+
- Gradual rollout capability (if needed)
325+
- Immediate rollback procedure
326+
- Monitoring alerts for performance degradation
327+
328+
## Monitoring and Observability
329+
330+
### Metrics to Monitor
331+
332+
**Performance Metrics:**
333+
- Lambda cold start duration
334+
- Lambda execution duration
335+
- Memory utilization
336+
- DynamoDB operation latency
337+
338+
**Functional Metrics:**
339+
- Error rates
340+
- Success rates for DynamoDB operations
341+
- Application workflow completion rates
342+
343+
**Cost Metrics:**
344+
- Lambda execution costs
345+
- DynamoDB request costs
346+
- Data transfer costs
347+
348+
### Logging Strategy
349+
350+
**Maintain Current Logging:**
351+
- Preserve existing console.log statements
352+
- Maintain error logging format
353+
- Ensure CloudWatch integration continues
354+
355+
**Enhanced Logging (Optional):**
356+
- Add v3-specific performance metrics
357+
- Include bundle size information
358+
- Log client initialization details
359+
360+
This design provides a comprehensive migration strategy that minimizes risk while maximizing the benefits of AWS SDK v3's improved architecture and performance characteristics.

0 commit comments

Comments
 (0)