@mytechtoday/augment-extensions 1.2.1 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/AGENTS.md +33 -1
  2. package/README.md +3 -3
  3. package/augment-extensions/domain-rules/software-architecture/README.md +143 -0
  4. package/augment-extensions/domain-rules/software-architecture/examples/banking-layered.md +961 -0
  5. package/augment-extensions/domain-rules/software-architecture/examples/ecommerce-microservices.md +990 -0
  6. package/augment-extensions/domain-rules/software-architecture/examples/iot-eventdriven.md +882 -0
  7. package/augment-extensions/domain-rules/software-architecture/examples/monolith-to-microservices-migration.md +703 -0
  8. package/augment-extensions/domain-rules/software-architecture/examples/serverless-imageprocessing.md +957 -0
  9. package/augment-extensions/domain-rules/software-architecture/examples/trading-eventdriven.md +747 -0
  10. package/augment-extensions/domain-rules/software-architecture/module.json +119 -0
  11. package/augment-extensions/domain-rules/software-architecture/rules/challenges-solutions.md +763 -0
  12. package/augment-extensions/domain-rules/software-architecture/rules/definitions-terminology.md +409 -0
  13. package/augment-extensions/domain-rules/software-architecture/rules/design-principles.md +684 -0
  14. package/augment-extensions/domain-rules/software-architecture/rules/evaluation-testing.md +1381 -0
  15. package/augment-extensions/domain-rules/software-architecture/rules/event-driven-architecture.md +616 -0
  16. package/augment-extensions/domain-rules/software-architecture/rules/fundamentals.md +306 -0
  17. package/augment-extensions/domain-rules/software-architecture/rules/industry-architectures.md +554 -0
  18. package/augment-extensions/domain-rules/software-architecture/rules/layered-architecture.md +776 -0
  19. package/augment-extensions/domain-rules/software-architecture/rules/microservices-architecture.md +503 -0
  20. package/augment-extensions/domain-rules/software-architecture/rules/modeling-documentation.md +1199 -0
  21. package/augment-extensions/domain-rules/software-architecture/rules/monolithic-architecture.md +351 -0
  22. package/augment-extensions/domain-rules/software-architecture/rules/principles.md +556 -0
  23. package/augment-extensions/domain-rules/software-architecture/rules/quality-attributes.md +797 -0
  24. package/augment-extensions/domain-rules/software-architecture/rules/scalability-performance.md +1345 -0
  25. package/augment-extensions/domain-rules/software-architecture/rules/security-architecture.md +1039 -0
  26. package/augment-extensions/domain-rules/software-architecture/rules/serverless-architecture.md +711 -0
  27. package/augment-extensions/domain-rules/software-architecture/rules/skills-development.md +568 -0
  28. package/augment-extensions/domain-rules/software-architecture/rules/tools-methodologies.md +961 -0
  29. package/augment-extensions/workflows/beads/rules/workflow.md +1 -1
  30. package/modules.md +40 -3
  31. package/package.json +1 -1
@@ -0,0 +1,711 @@
1
+ # Serverless Architecture
2
+
3
+ ## Overview
4
+
5
+ This document covers serverless architecture patterns, Function-as-a-Service (FaaS), stateless functions, and best practices for building event-driven, scalable applications without managing servers.
6
+
7
+ ---
8
+
9
+ ## Knowledge
10
+
11
+ ### What is Serverless Architecture?
12
+
13
+ **Definition**
14
+ - Cloud execution model where provider manages infrastructure
15
+ - Code runs in stateless compute containers
16
+ - Event-driven execution
17
+ - Automatic scaling
18
+ - Pay-per-execution pricing
19
+
20
+ **Core Principles**
21
+ - No server management
22
+ - Stateless functions
23
+ - Event-driven triggers
24
+ - Automatic scaling
25
+ - Built-in high availability
26
+
27
+ **Serverless Components**
28
+
29
+ **FaaS (Function-as-a-Service)**
30
+ - AWS Lambda, Azure Functions, Google Cloud Functions
31
+ - Execute code in response to events
32
+ - Millisecond billing
33
+ - Automatic scaling
34
+
35
+ **BaaS (Backend-as-a-Service)**
36
+ - Managed services: databases, authentication, storage
37
+ - Examples: AWS DynamoDB, Firebase, Auth0
38
+ - No infrastructure management
39
+
40
+ **Characteristics**
41
+ - Ephemeral execution (short-lived)
42
+ - Stateless (no persistent state in function)
43
+ - Cold start latency
44
+ - Execution time limits (e.g., 15 min for Lambda)
45
+ - Memory and CPU limits
46
+
47
+ ### When to Use Serverless
48
+
49
+ **Good Fit**
50
+ - Event-driven workloads
51
+ - Unpredictable or variable traffic
52
+ - Microservices and APIs
53
+ - Data processing pipelines
54
+ - Scheduled tasks (cron jobs)
55
+ - Webhooks and integrations
56
+ - Prototypes and MVPs
57
+
58
+ **Poor Fit**
59
+ - Long-running processes (> 15 minutes)
60
+ - Stateful applications
61
+ - Predictable, constant high load
62
+ - Low-latency requirements (< 100ms)
63
+ - Complex orchestration
64
+ - Legacy applications
65
+
66
+ ---
67
+
68
+ ## Skills
69
+
70
+ ### Function Design
71
+
72
+ **Stateless Functions**
73
+ ```javascript
74
+ // Good: Stateless function
75
+ exports.handler = async (event) => {
76
+ const userId = event.pathParameters.userId;
77
+
78
+ // Get data from external source
79
+ const user = await dynamodb.get({
80
+ TableName: 'Users',
81
+ Key: { userId }
82
+ }).promise();
83
+
84
+ return {
85
+ statusCode: 200,
86
+ body: JSON.stringify(user.Item)
87
+ };
88
+ };
89
+
90
+ // Bad: Stateful function (don't do this)
91
+ let requestCount = 0; // State persists across invocations!
92
+
93
+ exports.handler = async (event) => {
94
+ requestCount++; // Unreliable
95
+ // ...
96
+ };
97
+ ```
98
+
99
+ **Single Responsibility**
100
+ - One function, one purpose
101
+ - Small, focused functions
102
+ - Easy to test and maintain
103
+ - Independent deployment
104
+
105
+ **Function Size Guidelines**
106
+ - Keep functions small (< 500 lines)
107
+ - Minimize dependencies
108
+ - Fast cold start (< 3 seconds)
109
+ - Optimize package size
110
+
111
+ ### Event Sources and Triggers
112
+
113
+ **HTTP Triggers**
114
+ - API Gateway → Lambda
115
+ - REST APIs
116
+ - Webhooks
117
+ - GraphQL endpoints
118
+
119
+ **Storage Triggers**
120
+ - S3 object created/deleted
121
+ - File processing
122
+ - Image resizing
123
+ - Data transformation
124
+
125
+ **Database Triggers**
126
+ - DynamoDB Streams
127
+ - Change data capture
128
+ - Audit logging
129
+ - Data replication
130
+
131
+ **Message Queue Triggers**
132
+ - SQS, SNS, EventBridge
133
+ - Asynchronous processing
134
+ - Event-driven workflows
135
+ - Decoupled systems
136
+
137
+ **Scheduled Triggers**
138
+ - CloudWatch Events (cron)
139
+ - Periodic tasks
140
+ - Batch processing
141
+ - Cleanup jobs
142
+
143
+ ### Cold Start Optimization
144
+
145
+ **What is Cold Start?**
146
+ - First invocation after idle period
147
+ - Container initialization
148
+ - Code loading
149
+ - Dependency initialization
150
+ - Can add 1-5 seconds latency
151
+
152
+ **Optimization Techniques**
153
+
154
+ **Minimize Package Size**
155
+ ```javascript
156
+ // Good: Import only what you need
157
+ const { DynamoDB } = require('aws-sdk');
158
+
159
+ // Bad: Import entire SDK
160
+ const AWS = require('aws-sdk');
161
+ ```
162
+
163
+ **Lazy Loading**
164
+ ```javascript
165
+ let dynamodb;
166
+
167
+ exports.handler = async (event) => {
168
+ // Initialize on first use
169
+ if (!dynamodb) {
170
+ const { DynamoDB } = require('aws-sdk');
171
+ dynamodb = new DynamoDB.DocumentClient();
172
+ }
173
+
174
+ // Use dynamodb...
175
+ };
176
+ ```
177
+
178
+ **Provisioned Concurrency**
179
+ - Keep functions warm
180
+ - Pre-initialized containers
181
+ - Eliminates cold starts
182
+ - Higher cost
183
+
184
+ **Connection Reuse**
185
+ ```javascript
186
+ // Initialize outside handler (reused across invocations)
187
+ const { DynamoDB } = require('aws-sdk');
188
+ const dynamodb = new DynamoDB.DocumentClient();
189
+
190
+ exports.handler = async (event) => {
191
+ // Reuse connection
192
+ const result = await dynamodb.get({...}).promise();
193
+ return result;
194
+ };
195
+ ```
196
+
197
+ ### State Management
198
+
199
+ **External State Storage**
200
+ - DynamoDB for NoSQL data
201
+ - RDS for relational data
202
+ - S3 for files and objects
203
+ - ElastiCache for caching
204
+
205
+ **Temporary State**
206
+ - /tmp directory (512 MB - 10 GB)
207
+ - Ephemeral (cleared between cold starts)
208
+ - Use for temporary files
209
+
210
+ **Distributed State**
211
+ - Step Functions for workflow state
212
+ - DynamoDB for shared state
213
+ - Parameter Store for configuration
214
+ - Secrets Manager for credentials
215
+
216
+ ---
217
+
218
+ ## Examples
219
+
220
+ ### REST API with Lambda and API Gateway
221
+
222
+ **Function: Get User**
223
+ ```javascript
224
+ const { DynamoDB } = require('aws-sdk');
225
+ const dynamodb = new DynamoDB.DocumentClient();
226
+
227
+ exports.handler = async (event) => {
228
+ try {
229
+ const userId = event.pathParameters.userId;
230
+
231
+ const result = await dynamodb.get({
232
+ TableName: process.env.USERS_TABLE,
233
+ Key: { userId }
234
+ }).promise();
235
+
236
+ if (!result.Item) {
237
+ return {
238
+ statusCode: 404,
239
+ body: JSON.stringify({ error: 'User not found' })
240
+ };
241
+ }
242
+
243
+ return {
244
+ statusCode: 200,
245
+ headers: {
246
+ 'Content-Type': 'application/json',
247
+ 'Access-Control-Allow-Origin': '*'
248
+ },
249
+ body: JSON.stringify(result.Item)
250
+ };
251
+ } catch (error) {
252
+ console.error('Error:', error);
253
+ return {
254
+ statusCode: 500,
255
+ body: JSON.stringify({ error: 'Internal server error' })
256
+ };
257
+ }
258
+ };
259
+ ```
260
+
261
+ **Function: Create User**
262
+ ```javascript
263
+ const { DynamoDB } = require('aws-sdk');
264
+ const { v4: uuidv4 } = require('uuid');
265
+ const dynamodb = new DynamoDB.DocumentClient();
266
+
267
+ exports.handler = async (event) => {
268
+ try {
269
+ const body = JSON.parse(event.body);
270
+
271
+ // Validate input
272
+ if (!body.email || !body.name) {
273
+ return {
274
+ statusCode: 400,
275
+ body: JSON.stringify({
276
+ error: 'Email and name are required'
277
+ })
278
+ };
279
+ }
280
+
281
+ const user = {
282
+ userId: uuidv4(),
283
+ email: body.email,
284
+ name: body.name,
285
+ createdAt: new Date().toISOString()
286
+ };
287
+
288
+ await dynamodb.put({
289
+ TableName: process.env.USERS_TABLE,
290
+ Item: user
291
+ }).promise();
292
+
293
+ return {
294
+ statusCode: 201,
295
+ headers: {
296
+ 'Content-Type': 'application/json',
297
+ 'Access-Control-Allow-Origin': '*'
298
+ },
299
+ body: JSON.stringify(user)
300
+ };
301
+ } catch (error) {
302
+ console.error('Error:', error);
303
+ return {
304
+ statusCode: 500,
305
+ body: JSON.stringify({ error: 'Internal server error' })
306
+ };
307
+ }
308
+ };
309
+ ```
310
+
311
+ **Infrastructure as Code (Serverless Framework)**
312
+ ```yaml
313
+ service: user-api
314
+
315
+ provider:
316
+ name: aws
317
+ runtime: nodejs18.x
318
+ region: us-east-1
319
+ environment:
320
+ USERS_TABLE: ${self:service}-users-${self:provider.stage}
321
+ iamRoleStatements:
322
+ - Effect: Allow
323
+ Action:
324
+ - dynamodb:GetItem
325
+ - dynamodb:PutItem
326
+ - dynamodb:Query
327
+ Resource:
328
+ - arn:aws:dynamodb:${self:provider.region}:*:table/${self:provider.environment.USERS_TABLE}
329
+
330
+ functions:
331
+ getUser:
332
+ handler: handlers/getUser.handler
333
+ events:
334
+ - http:
335
+ path: users/{userId}
336
+ method: get
337
+ cors: true
338
+
339
+ createUser:
340
+ handler: handlers/createUser.handler
341
+ events:
342
+ - http:
343
+ path: users
344
+ method: post
345
+ cors: true
346
+
347
+ resources:
348
+ Resources:
349
+ UsersTable:
350
+ Type: AWS::DynamoDB::Table
351
+ Properties:
352
+ TableName: ${self:provider.environment.USERS_TABLE}
353
+ AttributeDefinitions:
354
+ - AttributeName: userId
355
+ AttributeType: S
356
+ KeySchema:
357
+ - AttributeName: userId
358
+ KeyType: HASH
359
+ BillingMode: PAY_PER_REQUEST
360
+ ```
361
+
362
+ ### Image Processing Pipeline
363
+
364
+ **S3 Trigger Function**
365
+ ```javascript
366
+ const AWS = require('aws-sdk');
367
+ const sharp = require('sharp');
368
+ const s3 = new AWS.S3();
369
+
370
+ exports.handler = async (event) => {
371
+ // Get S3 event details
372
+ const bucket = event.Records[0].s3.bucket.name;
373
+ const key = decodeURIComponent(
374
+ event.Records[0].s3.object.key.replace(/\+/g, ' ')
375
+ );
376
+
377
+ try {
378
+ // Download image from S3
379
+ const image = await s3.getObject({
380
+ Bucket: bucket,
381
+ Key: key
382
+ }).promise();
383
+
384
+ // Resize image
385
+ const resized = await sharp(image.Body)
386
+ .resize(800, 600, { fit: 'inside' })
387
+ .jpeg({ quality: 80 })
388
+ .toBuffer();
389
+
390
+ // Upload resized image
391
+ const outputKey = key.replace('uploads/', 'thumbnails/');
392
+ await s3.putObject({
393
+ Bucket: bucket,
394
+ Key: outputKey,
395
+ Body: resized,
396
+ ContentType: 'image/jpeg'
397
+ }).promise();
398
+
399
+ console.log(`Resized ${key} to ${outputKey}`);
400
+
401
+ return {
402
+ statusCode: 200,
403
+ body: JSON.stringify({
404
+ message: 'Image processed successfully',
405
+ thumbnail: outputKey
406
+ })
407
+ };
408
+ } catch (error) {
409
+ console.error('Error processing image:', error);
410
+ throw error;
411
+ }
412
+ };
413
+ ```
414
+
415
+ ### Event-Driven Workflow with Step Functions
416
+
417
+ **Order Processing Workflow**
418
+ ```json
419
+ {
420
+ "Comment": "Order processing workflow",
421
+ "StartAt": "ValidateOrder",
422
+ "States": {
423
+ "ValidateOrder": {
424
+ "Type": "Task",
425
+ "Resource": "arn:aws:lambda:us-east-1:123456789012:function:ValidateOrder",
426
+ "Next": "CheckInventory"
427
+ },
428
+ "CheckInventory": {
429
+ "Type": "Task",
430
+ "Resource": "arn:aws:lambda:us-east-1:123456789012:function:CheckInventory",
431
+ "Next": "InventoryAvailable?"
432
+ },
433
+ "InventoryAvailable?": {
434
+ "Type": "Choice",
435
+ "Choices": [
436
+ {
437
+ "Variable": "$.inventoryAvailable",
438
+ "BooleanEquals": true,
439
+ "Next": "ProcessPayment"
440
+ }
441
+ ],
442
+ "Default": "NotifyOutOfStock"
443
+ },
444
+ "ProcessPayment": {
445
+ "Type": "Task",
446
+ "Resource": "arn:aws:lambda:us-east-1:123456789012:function:ProcessPayment",
447
+ "Next": "PaymentSuccessful?"
448
+ },
449
+ "PaymentSuccessful?": {
450
+ "Type": "Choice",
451
+ "Choices": [
452
+ {
453
+ "Variable": "$.paymentStatus",
454
+ "StringEquals": "SUCCESS",
455
+ "Next": "FulfillOrder"
456
+ }
457
+ ],
458
+ "Default": "NotifyPaymentFailed"
459
+ },
460
+ "FulfillOrder": {
461
+ "Type": "Task",
462
+ "Resource": "arn:aws:lambda:us-east-1:123456789012:function:FulfillOrder",
463
+ "Next": "SendConfirmation"
464
+ },
465
+ "SendConfirmation": {
466
+ "Type": "Task",
467
+ "Resource": "arn:aws:lambda:us-east-1:123456789012:function:SendConfirmation",
468
+ "End": true
469
+ },
470
+ "NotifyOutOfStock": {
471
+ "Type": "Task",
472
+ "Resource": "arn:aws:lambda:us-east-1:123456789012:function:NotifyOutOfStock",
473
+ "End": true
474
+ },
475
+ "NotifyPaymentFailed": {
476
+ "Type": "Task",
477
+ "Resource": "arn:aws:lambda:us-east-1:123456789012:function:NotifyPaymentFailed",
478
+ "End": true
479
+ }
480
+ }
481
+ }
482
+ ```
483
+
484
+ **Lambda Function for Step**
485
+ ```javascript
486
+ exports.handler = async (event) => {
487
+ const { orderId, items } = event;
488
+
489
+ // Check inventory
490
+ const inventoryAvailable = await checkInventory(items);
491
+
492
+ return {
493
+ ...event,
494
+ inventoryAvailable,
495
+ checkedAt: new Date().toISOString()
496
+ };
497
+ };
498
+ ```
499
+
500
+ ### Scheduled Task (Cron Job)
501
+
502
+ **Daily Report Generator**
503
+ ```javascript
504
+ const AWS = require('aws-sdk');
505
+ const s3 = new AWS.S3();
506
+ const dynamodb = new AWS.DynamoDB.DocumentClient();
507
+
508
+ exports.handler = async (event) => {
509
+ try {
510
+ // Get yesterday's date
511
+ const yesterday = new Date();
512
+ yesterday.setDate(yesterday.getDate() - 1);
513
+ const dateStr = yesterday.toISOString().split('T')[0];
514
+
515
+ // Query orders from yesterday
516
+ const orders = await dynamodb.query({
517
+ TableName: process.env.ORDERS_TABLE,
518
+ IndexName: 'DateIndex',
519
+ KeyConditionExpression: 'orderDate = :date',
520
+ ExpressionAttributeValues: {
521
+ ':date': dateStr
522
+ }
523
+ }).promise();
524
+
525
+ // Generate report
526
+ const report = {
527
+ date: dateStr,
528
+ totalOrders: orders.Items.length,
529
+ totalRevenue: orders.Items.reduce(
530
+ (sum, order) => sum + order.total,
531
+ 0
532
+ ),
533
+ orders: orders.Items
534
+ };
535
+
536
+ // Save report to S3
537
+ await s3.putObject({
538
+ Bucket: process.env.REPORTS_BUCKET,
539
+ Key: `daily-reports/${dateStr}.json`,
540
+ Body: JSON.stringify(report, null, 2),
541
+ ContentType: 'application/json'
542
+ }).promise();
543
+
544
+ console.log(`Generated report for ${dateStr}`);
545
+
546
+ return {
547
+ statusCode: 200,
548
+ body: JSON.stringify({
549
+ message: 'Report generated successfully',
550
+ date: dateStr
551
+ })
552
+ };
553
+ } catch (error) {
554
+ console.error('Error generating report:', error);
555
+ throw error;
556
+ }
557
+ };
558
+ ```
559
+
560
+ **CloudWatch Event Rule (Serverless Framework)**
561
+ ```yaml
562
+ functions:
563
+ dailyReport:
564
+ handler: handlers/dailyReport.handler
565
+ events:
566
+ - schedule:
567
+ rate: cron(0 2 * * ? *) # Run at 2 AM UTC daily
568
+ enabled: true
569
+ ```
570
+
571
+ ---
572
+
573
+ ## Understanding
574
+
575
+ ### Advantages of Serverless Architecture
576
+
577
+ **No Server Management**
578
+ - No provisioning or maintenance
579
+ - Automatic OS updates
580
+ - Built-in high availability
581
+ - Focus on code, not infrastructure
582
+
583
+ **Automatic Scaling**
584
+ - Scales with demand
585
+ - Zero to thousands of requests
586
+ - No capacity planning
587
+ - Handles traffic spikes
588
+
589
+ **Cost Efficiency**
590
+ - Pay per execution
591
+ - No idle capacity costs
592
+ - Millisecond billing
593
+ - Free tier available
594
+
595
+ **Faster Time to Market**
596
+ - Rapid development
597
+ - Less operational overhead
598
+ - Built-in integrations
599
+ - Focus on business logic
600
+
601
+ **Built-in Fault Tolerance**
602
+ - Automatic retries
603
+ - Dead letter queues
604
+ - Multi-AZ deployment
605
+ - High availability
606
+
607
+ ### Challenges and Disadvantages
608
+
609
+ **Cold Start Latency**
610
+ - First invocation delay (1-5 seconds)
611
+ - Impacts user experience
612
+ - Varies by runtime and package size
613
+ - Mitigated with provisioned concurrency (cost)
614
+
615
+ **Execution Time Limits**
616
+ - AWS Lambda: 15 minutes max
617
+ - Not suitable for long-running tasks
618
+ - Need to break into smaller functions
619
+ - Use Step Functions for orchestration
620
+
621
+ **Vendor Lock-in**
622
+ - Platform-specific APIs
623
+ - Migration complexity
624
+ - Limited portability
625
+ - Dependency on provider
626
+
627
+ **Debugging Challenges**
628
+ - Distributed system complexity
629
+ - Limited local testing
630
+ - CloudWatch logs only
631
+ - Difficult to reproduce issues
632
+
633
+ **Stateless Constraints**
634
+ - No persistent state in function
635
+ - External storage required
636
+ - Connection overhead
637
+ - Complexity for stateful apps
638
+
639
+ **Cost at Scale**
640
+ - Can be expensive at high volume
641
+ - Unpredictable costs
642
+ - Need monitoring and optimization
643
+ - Compare with container/VM costs
644
+
645
+ ### Best Practices
646
+
647
+ **Function Design**
648
+ - Keep functions small and focused
649
+ - Minimize dependencies
650
+ - Optimize cold start time
651
+ - Use environment variables for configuration
652
+ - Implement proper error handling
653
+
654
+ **Security**
655
+ - Principle of least privilege (IAM)
656
+ - Encrypt sensitive data
657
+ - Use Secrets Manager for credentials
658
+ - Validate all inputs
659
+ - Enable VPC for private resources
660
+
661
+ **Performance**
662
+ - Reuse connections outside handler
663
+ - Use provisioned concurrency for critical paths
664
+ - Optimize package size
665
+ - Implement caching
666
+ - Monitor and optimize memory allocation
667
+
668
+ **Monitoring and Logging**
669
+ - Structured logging
670
+ - CloudWatch metrics
671
+ - Distributed tracing (X-Ray)
672
+ - Alerting on errors
673
+ - Cost monitoring
674
+
675
+ **Testing**
676
+ - Unit tests for business logic
677
+ - Integration tests with LocalStack
678
+ - Load testing
679
+ - Chaos engineering
680
+ - Canary deployments
681
+
682
+ ---
683
+
684
+ ## References
685
+
686
+ - **Books**
687
+ - "Serverless Architectures on AWS" by Peter Sbarski
688
+ - "AWS Lambda in Action" by Danilo Poccia
689
+ - "Serverless Design Patterns" by Brian Zambrano
690
+
691
+ - **Patterns**
692
+ - API Gateway Pattern
693
+ - Event-Driven Pattern
694
+ - Fan-Out Pattern
695
+ - Choreography Pattern
696
+ - Orchestration Pattern (Step Functions)
697
+
698
+ - **Platforms**
699
+ - AWS Lambda
700
+ - Azure Functions
701
+ - Google Cloud Functions
702
+ - Cloudflare Workers
703
+ - Vercel Functions
704
+
705
+ - **Frameworks**
706
+ - Serverless Framework
707
+ - AWS SAM (Serverless Application Model)
708
+ - Terraform
709
+ - Pulumi
710
+
711
+