cdk-cost-analyzer 0.1.1

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 (228) hide show
  1. package/.cdk-cost-analyzer-cache/metadata.json +12 -0
  2. package/.gitlab-ci.yml +214 -0
  3. package/.husky/pre-commit +12 -0
  4. package/.kiro/hooks/accessibility-audit.kiro.hook +18 -0
  5. package/.kiro/hooks/api-schema-validation.kiro.hook +21 -0
  6. package/.kiro/hooks/auto-test-on-save.kiro.hook +19 -0
  7. package/.kiro/hooks/cdk-synth-on-change.kiro.hook +20 -0
  8. package/.kiro/hooks/code-coverage-check.kiro.hook +14 -0
  9. package/.kiro/hooks/commit-message-helper.kiro.hook +14 -0
  10. package/.kiro/hooks/dependency-update-check.kiro.hook +14 -0
  11. package/.kiro/hooks/env-file-validation.kiro.hook +18 -0
  12. package/.kiro/hooks/lint-and-format-on-save.kiro.hook +21 -0
  13. package/.kiro/hooks/mcp-config-validation.kiro.hook +17 -0
  14. package/.kiro/hooks/mcp-server-test.kiro.hook +14 -0
  15. package/.kiro/hooks/performance-analysis.kiro.hook +14 -0
  16. package/.kiro/hooks/readme-spell-check.kiro.hook +14 -0
  17. package/.kiro/hooks/security-scan-on-dependency-change.kiro.hook +21 -0
  18. package/.kiro/hooks/translation-update.kiro.hook +18 -0
  19. package/.kiro/hooks/update-documentation.kiro.hook +18 -0
  20. package/.kiro/settings/mcp.json +20 -0
  21. package/.kiro/specs/cdk-cost-analyzer/design.md +620 -0
  22. package/.kiro/specs/cdk-cost-analyzer/requirements.md +183 -0
  23. package/.kiro/specs/cdk-cost-analyzer/tasks.md +357 -0
  24. package/.kiro/specs/github-actions-ci/design.md +281 -0
  25. package/.kiro/specs/github-actions-ci/requirements.md +86 -0
  26. package/.kiro/specs/github-actions-ci/tasks.md +115 -0
  27. package/.kiro/specs/nlb-calculator-test-coverage/design.md +190 -0
  28. package/.kiro/specs/nlb-calculator-test-coverage/requirements.md +84 -0
  29. package/.kiro/specs/nlb-calculator-test-coverage/tasks.md +150 -0
  30. package/.kiro/specs/production-readiness/design.md +1213 -0
  31. package/.kiro/specs/production-readiness/requirements.md +312 -0
  32. package/.kiro/specs/production-readiness/tasks.md +269 -0
  33. package/.kiro/specs/repository-cleanup/design.md +283 -0
  34. package/.kiro/specs/repository-cleanup/requirements.md +74 -0
  35. package/.kiro/specs/repository-cleanup/tasks.md +64 -0
  36. package/.kiro/steering/aws-cli-best-practices.md +41 -0
  37. package/.kiro/steering/cdk-best-practices.md +49 -0
  38. package/.kiro/steering/development-standards.md +54 -0
  39. package/.kiro/steering/docker-best-practices.md +34 -0
  40. package/.kiro/steering/documentation-style.md +151 -0
  41. package/.kiro/steering/git-best-practices.md +37 -0
  42. package/.kiro/steering/mcp-best-practices.md +95 -0
  43. package/.kiro/steering/python-best-practices.md +48 -0
  44. package/.kiro/steering/react-best-practices.md +44 -0
  45. package/.kiro/steering/security-best-practices.md +41 -0
  46. package/.kiro/steering/testing-best-practices.md +59 -0
  47. package/.kiro/steering/typescript-best-practices.md +40 -0
  48. package/CHANGELOG.md +49 -0
  49. package/CONTRIBUTING.md +258 -0
  50. package/LICENSE +19 -0
  51. package/README.md +480 -0
  52. package/SECURITY.md +117 -0
  53. package/dist/api/index.d.ts +11 -0
  54. package/dist/api/index.js +65 -0
  55. package/dist/api/types.d.ts +15 -0
  56. package/dist/api/types.js +3 -0
  57. package/dist/cli/index.d.ts +2 -0
  58. package/dist/cli/index.js +262 -0
  59. package/dist/config/ConfigManager.d.ts +40 -0
  60. package/dist/config/ConfigManager.js +238 -0
  61. package/dist/config/index.d.ts +2 -0
  62. package/dist/config/index.js +19 -0
  63. package/dist/config/types.d.ts +72 -0
  64. package/dist/config/types.js +15 -0
  65. package/dist/diff/DiffEngine.d.ts +7 -0
  66. package/dist/diff/DiffEngine.js +73 -0
  67. package/dist/diff/index.d.ts +2 -0
  68. package/dist/diff/index.js +21 -0
  69. package/dist/diff/types.d.ts +20 -0
  70. package/dist/diff/types.js +3 -0
  71. package/dist/integrations/GitLabIntegration.d.ts +7 -0
  72. package/dist/integrations/GitLabIntegration.js +45 -0
  73. package/dist/integrations/index.d.ts +2 -0
  74. package/dist/integrations/index.js +21 -0
  75. package/dist/integrations/types.d.ts +11 -0
  76. package/dist/integrations/types.js +13 -0
  77. package/dist/parser/TemplateParser.d.ts +8 -0
  78. package/dist/parser/TemplateParser.js +75 -0
  79. package/dist/parser/index.d.ts +2 -0
  80. package/dist/parser/index.js +22 -0
  81. package/dist/parser/types.d.ts +30 -0
  82. package/dist/parser/types.js +3 -0
  83. package/dist/pipeline/PipelineOrchestrator.d.ts +23 -0
  84. package/dist/pipeline/PipelineOrchestrator.js +191 -0
  85. package/dist/pipeline/index.d.ts +2 -0
  86. package/dist/pipeline/index.js +19 -0
  87. package/dist/pipeline/types.d.ts +41 -0
  88. package/dist/pipeline/types.js +13 -0
  89. package/dist/pricing/CacheManager.d.ts +75 -0
  90. package/dist/pricing/CacheManager.js +195 -0
  91. package/dist/pricing/PricingClient.d.ts +17 -0
  92. package/dist/pricing/PricingClient.js +122 -0
  93. package/dist/pricing/PricingService.d.ts +16 -0
  94. package/dist/pricing/PricingService.js +149 -0
  95. package/dist/pricing/calculators/ALBCalculator.d.ts +16 -0
  96. package/dist/pricing/calculators/ALBCalculator.js +163 -0
  97. package/dist/pricing/calculators/APIGatewayCalculator.d.ts +10 -0
  98. package/dist/pricing/calculators/APIGatewayCalculator.js +177 -0
  99. package/dist/pricing/calculators/CloudFrontCalculator.d.ts +59 -0
  100. package/dist/pricing/calculators/CloudFrontCalculator.js +151 -0
  101. package/dist/pricing/calculators/DynamoDBCalculator.d.ts +9 -0
  102. package/dist/pricing/calculators/DynamoDBCalculator.js +146 -0
  103. package/dist/pricing/calculators/EC2Calculator.d.ts +7 -0
  104. package/dist/pricing/calculators/EC2Calculator.js +80 -0
  105. package/dist/pricing/calculators/ECSCalculator.d.ts +9 -0
  106. package/dist/pricing/calculators/ECSCalculator.js +116 -0
  107. package/dist/pricing/calculators/ElastiCacheCalculator.d.ts +8 -0
  108. package/dist/pricing/calculators/ElastiCacheCalculator.js +106 -0
  109. package/dist/pricing/calculators/LambdaCalculator.d.ts +13 -0
  110. package/dist/pricing/calculators/LambdaCalculator.js +111 -0
  111. package/dist/pricing/calculators/NLBCalculator.d.ts +16 -0
  112. package/dist/pricing/calculators/NLBCalculator.js +138 -0
  113. package/dist/pricing/calculators/NatGatewayCalculator.d.ts +12 -0
  114. package/dist/pricing/calculators/NatGatewayCalculator.js +116 -0
  115. package/dist/pricing/calculators/RDSCalculator.d.ts +9 -0
  116. package/dist/pricing/calculators/RDSCalculator.js +103 -0
  117. package/dist/pricing/calculators/S3Calculator.d.ts +8 -0
  118. package/dist/pricing/calculators/S3Calculator.js +68 -0
  119. package/dist/pricing/calculators/VPCEndpointCalculator.d.ts +12 -0
  120. package/dist/pricing/calculators/VPCEndpointCalculator.js +129 -0
  121. package/dist/pricing/index.d.ts +10 -0
  122. package/dist/pricing/index.js +37 -0
  123. package/dist/pricing/types.d.ts +53 -0
  124. package/dist/pricing/types.js +22 -0
  125. package/dist/releasetag.txt +1 -0
  126. package/dist/reporter/Reporter.d.ts +18 -0
  127. package/dist/reporter/Reporter.js +412 -0
  128. package/dist/reporter/index.d.ts +2 -0
  129. package/dist/reporter/index.js +21 -0
  130. package/dist/reporter/types.d.ts +72 -0
  131. package/dist/reporter/types.js +3 -0
  132. package/dist/synthesis/SynthesisOrchestrator.d.ts +26 -0
  133. package/dist/synthesis/SynthesisOrchestrator.js +243 -0
  134. package/dist/synthesis/index.d.ts +2 -0
  135. package/dist/synthesis/index.js +19 -0
  136. package/dist/synthesis/types.d.ts +17 -0
  137. package/dist/synthesis/types.js +13 -0
  138. package/dist/threshold/ThresholdEnforcer.d.ts +29 -0
  139. package/dist/threshold/ThresholdEnforcer.js +143 -0
  140. package/dist/threshold/index.d.ts +2 -0
  141. package/dist/threshold/index.js +19 -0
  142. package/dist/threshold/types.d.ts +15 -0
  143. package/dist/threshold/types.js +17 -0
  144. package/docs/CALCULATORS.md +820 -0
  145. package/docs/CI_CD.md +608 -0
  146. package/docs/CONFIGURATION.md +407 -0
  147. package/docs/DEVELOPMENT.md +387 -0
  148. package/docs/RELEASE.md +223 -0
  149. package/docs/TROUBLESHOOTING.md +847 -0
  150. package/examples/.cdk-cost-analyzer.yml +85 -0
  151. package/examples/.gitlab-ci.yml +125 -0
  152. package/examples/api-usage.js +26 -0
  153. package/examples/complex/base.json +16 -0
  154. package/examples/complex/target.json +29 -0
  155. package/examples/monorepo/.gitlab-ci.yml +251 -0
  156. package/examples/monorepo/README.md +341 -0
  157. package/examples/monorepo/package.json +27 -0
  158. package/examples/monorepo/packages/backend-infra/.cdk-cost-analyzer.yml +34 -0
  159. package/examples/monorepo/packages/backend-infra/bin/app.ts +16 -0
  160. package/examples/monorepo/packages/backend-infra/cdk.json +7 -0
  161. package/examples/monorepo/packages/backend-infra/lib/backend-stack.ts +128 -0
  162. package/examples/monorepo/packages/backend-infra/package.json +30 -0
  163. package/examples/monorepo/packages/backend-infra/tsconfig.json +11 -0
  164. package/examples/monorepo/packages/data-infra/.cdk-cost-analyzer.yml +38 -0
  165. package/examples/monorepo/packages/data-infra/bin/app.ts +16 -0
  166. package/examples/monorepo/packages/data-infra/cdk.json +7 -0
  167. package/examples/monorepo/packages/data-infra/lib/data-stack.ts +121 -0
  168. package/examples/monorepo/packages/data-infra/package.json +30 -0
  169. package/examples/monorepo/packages/data-infra/tsconfig.json +11 -0
  170. package/examples/monorepo/packages/frontend-infra/.cdk-cost-analyzer.yml +31 -0
  171. package/examples/monorepo/packages/frontend-infra/bin/app.ts +16 -0
  172. package/examples/monorepo/packages/frontend-infra/cdk.json +7 -0
  173. package/examples/monorepo/packages/frontend-infra/lib/frontend-stack.ts +60 -0
  174. package/examples/monorepo/packages/frontend-infra/package.json +30 -0
  175. package/examples/monorepo/packages/frontend-infra/tsconfig.json +11 -0
  176. package/examples/monorepo/tsconfig.json +35 -0
  177. package/examples/multi-stack/.cdk-cost-analyzer.yml +72 -0
  178. package/examples/multi-stack/.gitlab-ci.yml +184 -0
  179. package/examples/multi-stack/README.md +279 -0
  180. package/examples/multi-stack/bin/app.ts +36 -0
  181. package/examples/multi-stack/cdk.json +72 -0
  182. package/examples/multi-stack/lib/compute-stack.ts +128 -0
  183. package/examples/multi-stack/lib/networking-stack.ts +69 -0
  184. package/examples/multi-stack/lib/storage-stack.ts +141 -0
  185. package/examples/multi-stack/package-lock.json +4437 -0
  186. package/examples/multi-stack/package.json +42 -0
  187. package/examples/multi-stack/tsconfig.json +34 -0
  188. package/examples/simple/base.json +8 -0
  189. package/examples/simple/target.json +14 -0
  190. package/examples/single-stack/.NVP +0 -0
  191. package/examples/single-stack/.cdk-cost-analyzer.yml +52 -0
  192. package/examples/single-stack/.gitlab-ci.yml +126 -0
  193. package/examples/single-stack/README.md +184 -0
  194. package/examples/single-stack/UeK +0 -0
  195. package/examples/single-stack/bin/app.ts +16 -0
  196. package/examples/single-stack/cdk.json +72 -0
  197. package/examples/single-stack/lib/infrastructure-stack.ts +119 -0
  198. package/examples/single-stack/package-lock.json +4443 -0
  199. package/examples/single-stack/package.json +38 -0
  200. package/examples/single-stack/tsconfig.json +34 -0
  201. package/package.json +139 -0
  202. package/test-cdk-project/README-COMPUTE.md +141 -0
  203. package/test-cdk-project/README.md +95 -0
  204. package/test-cdk-project/app-with-compute.js +102 -0
  205. package/test-cdk-project/app.js +81 -0
  206. package/test-cdk-project/cdk-compute.json +3 -0
  207. package/test-cdk-project/cdk.context.json +7 -0
  208. package/test-cdk-project/cdk.json +3 -0
  209. package/test-cdk-project/cdk.out/TestStack.assets.json +21 -0
  210. package/test-cdk-project/cdk.out/TestStack.template.json +115 -0
  211. package/test-cdk-project/cdk.out/cdk.out +1 -0
  212. package/test-cdk-project/cdk.out/manifest.json +503 -0
  213. package/test-cdk-project/cdk.out/tree.json +1 -0
  214. package/test-cdk-project/cdk.out.base/TestStack.assets.json +21 -0
  215. package/test-cdk-project/cdk.out.base/TestStack.template.json +115 -0
  216. package/test-cdk-project/cdk.out.base/cdk.out +1 -0
  217. package/test-cdk-project/cdk.out.base/manifest.json +503 -0
  218. package/test-cdk-project/cdk.out.base/tree.json +1 -0
  219. package/test-cdk-project/cdk.out.target/TestStack.assets.json +21 -0
  220. package/test-cdk-project/cdk.out.target/TestStack.template.json +183 -0
  221. package/test-cdk-project/cdk.out.target/cdk.out +1 -0
  222. package/test-cdk-project/cdk.out.target/manifest.json +521 -0
  223. package/test-cdk-project/cdk.out.target/tree.json +1 -0
  224. package/test-cdk-project/package-lock.json +422 -0
  225. package/test-cdk-project/package.json +17 -0
  226. package/tools/workflows/README.md +102 -0
  227. package/tools/workflows/validate-workflows.js +109 -0
  228. package/tools/workflows/workflow-utils.ts +181 -0
@@ -0,0 +1,279 @@
1
+ # Multi-Stack CDK Cost Analyzer Example
2
+
3
+ This example demonstrates how to integrate CDK Cost Analyzer into a multi-stack CDK application with separate networking, compute, and storage layers.
4
+
5
+ ## Project Structure
6
+
7
+ ```
8
+ multi-stack/
9
+ ├── bin/
10
+ │ └── app.ts # CDK application entry point
11
+ ├── lib/
12
+ │ ├── networking-stack.ts # VPC and networking resources
13
+ │ ├── compute-stack.ts # ECS and compute resources
14
+ │ └── storage-stack.ts # RDS and storage resources
15
+ ├── .cdk-cost-analyzer.yml # Cost analyzer configuration
16
+ ├── .gitlab-ci.yml # GitLab CI pipeline
17
+ ├── cdk.json # CDK configuration
18
+ ├── package.json # Node.js dependencies
19
+ ├── tsconfig.json # TypeScript configuration
20
+ └── README.md # This file
21
+ ```
22
+
23
+ ## Architecture Overview
24
+
25
+ This example creates a three-tier application infrastructure across multiple stacks:
26
+
27
+ ### Networking Stack
28
+ - **Amazon VPC**: Virtual private cloud with public and private subnets
29
+ - **NAT Gateway**: Network address translation for private subnet internet access
30
+ - **VPC Endpoints**: Private connectivity to AWS services
31
+
32
+ ### Compute Stack
33
+ - **Amazon ECS Cluster**: Container orchestration
34
+ - **Application Load Balancer**: Traffic distribution
35
+ - **ECS Service**: Containerized application
36
+
37
+ ### Storage Stack
38
+ - **Amazon RDS**: PostgreSQL database
39
+ - **Amazon ElastiCache**: Redis cache cluster
40
+ - **Amazon S3**: Object storage for application data
41
+
42
+ ## Why Multi-Stack?
43
+
44
+ Multi-stack architectures provide several benefits:
45
+
46
+ - **Separation of Concerns**: Network, compute, and storage managed independently
47
+ - **Deployment Flexibility**: Update individual layers without affecting others
48
+ - **Resource Limits**: Stay within CloudFormation's 500-resource limit per stack
49
+ - **Team Organization**: Different teams can own different stacks
50
+ - **Cost Tracking**: Easier to track costs per infrastructure layer
51
+
52
+ ## Prerequisites
53
+
54
+ - Node.js 18 or later
55
+ - AWS CDK CLI: `npm install -g aws-cdk`
56
+ - AWS account with appropriate credentials
57
+ - GitLab repository with CI/CD enabled
58
+
59
+ ## Setup Instructions
60
+
61
+ ### 1. Install Dependencies
62
+
63
+ ```bash
64
+ cd examples/multi-stack
65
+ npm install
66
+ ```
67
+
68
+ ### 2. Configure AWS Credentials
69
+
70
+ For local development:
71
+
72
+ ```bash
73
+ export AWS_ACCESS_KEY_ID=your-access-key
74
+ export AWS_SECRET_ACCESS_KEY=your-secret-key
75
+ export AWS_REGION=us-east-1
76
+ ```
77
+
78
+ For GitLab CI, configure these as CI/CD variables in your GitLab project settings.
79
+
80
+ ### 3. Bootstrap CDK (First Time Only)
81
+
82
+ ```bash
83
+ cdk bootstrap aws://ACCOUNT-ID/REGION
84
+ ```
85
+
86
+ ### 4. Review Configuration
87
+
88
+ Edit `.cdk-cost-analyzer.yml` to adjust cost thresholds and usage assumptions for your needs.
89
+
90
+ ## Local Development
91
+
92
+ ### Synthesize All Stacks
93
+
94
+ ```bash
95
+ cdk synth
96
+ ```
97
+
98
+ ### Deploy All Stacks
99
+
100
+ ```bash
101
+ cdk deploy --all
102
+ ```
103
+
104
+ ### Deploy Individual Stack
105
+
106
+ ```bash
107
+ cdk deploy NetworkingStack
108
+ cdk deploy ComputeStack
109
+ cdk deploy StorageStack
110
+ ```
111
+
112
+ ### Run Cost Analysis Locally
113
+
114
+ ```bash
115
+ # Install cost analyzer
116
+ npm install -g cdk-cost-analyzer
117
+
118
+ # Analyze cost impact across all stacks
119
+ cdk-cost-analyzer pipeline \
120
+ --base-branch main \
121
+ --target-branch feature/my-changes \
122
+ --region us-east-1
123
+ ```
124
+
125
+ ## Understanding Multi-Stack Cost Analysis
126
+
127
+ When analyzing multi-stack applications, CDK Cost Analyzer:
128
+
129
+ 1. **Identifies All Stacks**: Automatically detects all CloudFormation templates
130
+ 2. **Per-Stack Analysis**: Calculates cost changes for each stack independently
131
+ 3. **Aggregated Total**: Sums costs across all stacks for total impact
132
+ 4. **Detailed Breakdown**: Shows which stack contributes most to cost changes
133
+
134
+ ### Example Cost Report
135
+
136
+ ```
137
+ Cost Analysis Summary
138
+ =====================
139
+
140
+ Total Cost Delta: +$245.50/month
141
+
142
+ Per-Stack Breakdown:
143
+ - NetworkingStack: +$45.00/month
144
+ - NAT Gateway: +$32.40/month
145
+ - VPC Endpoints: +$12.60/month
146
+
147
+ - ComputeStack: +$150.00/month
148
+ - ECS Tasks: +$120.00/month
149
+ - Application Load Balancer: +$30.00/month
150
+
151
+ - StorageStack: +$50.50/month
152
+ - RDS Instance: +$35.00/month
153
+ - ElastiCache: +$15.50/month
154
+ ```
155
+
156
+ ## GitLab CI/CD Integration
157
+
158
+ The `.gitlab-ci.yml` file configures automatic cost analysis for merge requests with multi-stack support.
159
+
160
+ ### Pipeline Stages
161
+
162
+ 1. **Build**: Install dependencies
163
+ 2. **Test**: Run application tests
164
+ 3. **Cost Analysis**: Analyze infrastructure cost changes across all stacks
165
+ 4. **Deploy**: Deploy stacks to AWS (manual approval required if cost threshold exceeded)
166
+
167
+ ### Cost Thresholds
168
+
169
+ The pipeline enforces cost thresholds defined in `.cdk-cost-analyzer.yml`:
170
+
171
+ - **Warning**: $100/month - Pipeline passes but displays warning
172
+ - **Error**: $500/month - Pipeline fails, requires manual review
173
+
174
+ Note: Thresholds apply to the total cost across all stacks.
175
+
176
+ ## Customizing Usage Assumptions
177
+
178
+ Edit `.cdk-cost-analyzer.yml` to reflect your actual usage patterns:
179
+
180
+ ```yaml
181
+ usageAssumptions:
182
+ natGateway:
183
+ dataProcessedGB: 500 # Monthly data processed through NAT Gateway
184
+
185
+ alb:
186
+ newConnectionsPerSecond: 50
187
+ activeConnectionsPerMinute: 5000
188
+ processedBytesGB: 1000
189
+
190
+ rds:
191
+ instanceClass: db.t3.medium
192
+ storageGB: 100
193
+ backupRetentionDays: 7
194
+
195
+ elasticache:
196
+ nodeType: cache.t3.micro
197
+ numNodes: 2
198
+ ```
199
+
200
+ ## Stack Dependencies
201
+
202
+ The stacks have the following dependencies:
203
+
204
+ ```
205
+ NetworkingStack (base)
206
+
207
+ ComputeStack (depends on VPC)
208
+
209
+ StorageStack (depends on VPC and security groups)
210
+ ```
211
+
212
+ CDK automatically handles deployment order based on these dependencies.
213
+
214
+ ## Troubleshooting
215
+
216
+ ### Stack Dependency Errors
217
+
218
+ **Issue**: Deployment fails due to missing resources from other stacks
219
+
220
+ **Solution**: Ensure stacks are deployed in the correct order:
221
+ 1. NetworkingStack first
222
+ 2. ComputeStack second
223
+ 3. StorageStack last
224
+
225
+ Or use `cdk deploy --all` to deploy in dependency order automatically.
226
+
227
+ ### Cost Analysis Shows Unexpected Changes
228
+
229
+ **Issue**: Cost report shows changes in stacks you didn't modify
230
+
231
+ **Solution**: This is normal when:
232
+ - Stack dependencies cause resource updates
233
+ - CDK updates resource configurations automatically
234
+ - Cross-stack references change
235
+
236
+ Review the detailed per-stack breakdown to understand the changes.
237
+
238
+ ### Pipeline Timeout
239
+
240
+ **Issue**: Cost analysis stage times out in GitLab CI
241
+
242
+ **Solution**: Multi-stack analysis takes longer. Increase timeout:
243
+
244
+ ```yaml
245
+ cost-analysis:
246
+ timeout: 15m # Increase from default 1h
247
+ ```
248
+
249
+ ## Best Practices
250
+
251
+ ### Stack Organization
252
+
253
+ - **Keep stacks focused**: Each stack should have a clear purpose
254
+ - **Minimize cross-stack references**: Reduces coupling between stacks
255
+ - **Use consistent naming**: Makes cost tracking easier
256
+
257
+ ### Cost Management
258
+
259
+ - **Set per-stack budgets**: Track costs for each infrastructure layer
260
+ - **Review stack-level changes**: Understand which layer drives cost increases
261
+ - **Optimize expensive stacks**: Focus optimization efforts where they matter most
262
+
263
+ ### Deployment Strategy
264
+
265
+ - **Deploy networking first**: Establish foundation before other resources
266
+ - **Test incrementally**: Deploy and test each stack before moving to the next
267
+ - **Use stack policies**: Protect critical resources from accidental updates
268
+
269
+ ## Next Steps
270
+
271
+ - Review [Configuration Documentation](../../docs/CONFIGURATION.md) for advanced options
272
+ - Explore [Monorepo Example](../monorepo/) for multiple applications
273
+ - Check [Troubleshooting Guide](../../docs/TROUBLESHOOTING.md) for common issues
274
+
275
+ ## Additional Resources
276
+
277
+ - [AWS CDK Multi-Stack Documentation](https://docs.aws.amazon.com/cdk/v2/guide/stack_how_to_create_multiple_stacks.html)
278
+ - [CDK Cost Analyzer Documentation](../../README.md)
279
+ - [GitLab CI/CD Documentation](https://docs.gitlab.com/ee/ci/)
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+ import 'source-map-support/register';
3
+ import * as cdk from 'aws-cdk-lib';
4
+ import { NetworkingStack } from '../lib/networking-stack';
5
+ import { ComputeStack } from '../lib/compute-stack';
6
+ import { StorageStack } from '../lib/storage-stack';
7
+
8
+ const app = new cdk.App();
9
+
10
+ const env = {
11
+ account: process.env.CDK_DEFAULT_ACCOUNT,
12
+ region: process.env.CDK_DEFAULT_REGION || 'us-east-1',
13
+ };
14
+
15
+ // Create networking stack (foundation)
16
+ const networkingStack = new NetworkingStack(app, 'NetworkingStack', {
17
+ env,
18
+ description: 'Multi-stack example - Networking layer (VPC, NAT Gateway, VPC Endpoints)',
19
+ });
20
+
21
+ // Create compute stack (depends on networking)
22
+ const computeStack = new ComputeStack(app, 'ComputeStack', {
23
+ env,
24
+ vpc: networkingStack.vpc,
25
+ description: 'Multi-stack example - Compute layer (ECS, ALB)',
26
+ });
27
+
28
+ // Create storage stack (depends on networking and compute)
29
+ const storageStack = new StorageStack(app, 'StorageStack', {
30
+ env,
31
+ vpc: networkingStack.vpc,
32
+ appSecurityGroup: computeStack.appSecurityGroup,
33
+ description: 'Multi-stack example - Storage layer (RDS, ElastiCache, S3)',
34
+ });
35
+
36
+ app.synth();
@@ -0,0 +1,72 @@
1
+ {
2
+ "app": "npx ts-node --prefer-ts-exts bin/app.ts",
3
+ "watch": {
4
+ "include": [
5
+ "**"
6
+ ],
7
+ "exclude": [
8
+ "README.md",
9
+ "cdk*.json",
10
+ "**/*.d.ts",
11
+ "**/*.js",
12
+ "tsconfig.json",
13
+ "package*.json",
14
+ "yarn.lock",
15
+ "node_modules",
16
+ "test"
17
+ ]
18
+ },
19
+ "context": {
20
+ "@aws-cdk/aws-lambda:recognizeLayerVersion": true,
21
+ "@aws-cdk/core:checkSecretUsage": true,
22
+ "@aws-cdk/core:target-partitions": [
23
+ "aws",
24
+ "aws-cn"
25
+ ],
26
+ "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
27
+ "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
28
+ "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
29
+ "@aws-cdk/aws-iam:minimizePolicies": true,
30
+ "@aws-cdk/core:validateSnapshotRemovalPolicy": true,
31
+ "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
32
+ "@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
33
+ "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
34
+ "@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
35
+ "@aws-cdk/core:enablePartitionLiterals": true,
36
+ "@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
37
+ "@aws-cdk/aws-iam:standardizedServicePrincipals": true,
38
+ "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true,
39
+ "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true,
40
+ "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true,
41
+ "@aws-cdk/aws-route53-patters:useCertificate": true,
42
+ "@aws-cdk/customresources:installLatestAwsSdkDefault": false,
43
+ "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true,
44
+ "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true,
45
+ "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true,
46
+ "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true,
47
+ "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true,
48
+ "@aws-cdk/aws-redshift:columnId": true,
49
+ "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true,
50
+ "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true,
51
+ "@aws-cdk/aws-apigateway:requestValidatorUniqueId": true,
52
+ "@aws-cdk/aws-kms:aliasNameRef": true,
53
+ "@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true,
54
+ "@aws-cdk/core:includePrefixInUniqueNameGeneration": true,
55
+ "@aws-cdk/aws-efs:denyAnonymousAccess": true,
56
+ "@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true,
57
+ "@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true,
58
+ "@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true,
59
+ "@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true,
60
+ "@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true,
61
+ "@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true,
62
+ "@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": true,
63
+ "@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": true,
64
+ "@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": true,
65
+ "@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": true,
66
+ "@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": true,
67
+ "@aws-cdk/aws-eks:nodegroupNameAttribute": true,
68
+ "@aws-cdk/aws-ec2:ebsDefaultGp3Volume": true,
69
+ "@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": true,
70
+ "@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": false
71
+ }
72
+ }
@@ -0,0 +1,128 @@
1
+ import * as cdk from 'aws-cdk-lib';
2
+ import * as ec2 from 'aws-cdk-lib/aws-ec2';
3
+ import * as ecs from 'aws-cdk-lib/aws-ecs';
4
+ import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2';
5
+ import { Construct } from 'constructs';
6
+
7
+ export interface ComputeStackProps extends cdk.StackProps {
8
+ vpc: ec2.IVpc;
9
+ }
10
+
11
+ /**
12
+ * Compute stack - Application layer
13
+ *
14
+ * Creates ECS cluster, Application Load Balancer, and containerized application
15
+ */
16
+ export class ComputeStack extends cdk.Stack {
17
+ public readonly appSecurityGroup: ec2.SecurityGroup;
18
+
19
+ constructor(scope: Construct, id: string, props: ComputeStackProps) {
20
+ super(scope, id, props);
21
+
22
+ const { vpc } = props;
23
+
24
+ // Security group for application
25
+ this.appSecurityGroup = new ec2.SecurityGroup(this, 'AppSecurityGroup', {
26
+ vpc,
27
+ description: 'Security group for application containers',
28
+ allowAllOutbound: true,
29
+ });
30
+
31
+ // ECS Cluster
32
+ const cluster = new ecs.Cluster(this, 'Cluster', {
33
+ clusterName: 'multi-stack-cluster',
34
+ vpc,
35
+ containerInsights: true,
36
+ });
37
+
38
+ // Application Load Balancer
39
+ const alb = new elbv2.ApplicationLoadBalancer(this, 'ALB', {
40
+ loadBalancerName: 'multi-stack-alb',
41
+ vpc,
42
+ internetFacing: true,
43
+ deletionProtection: false,
44
+ });
45
+
46
+ // ALB Target Group
47
+ const targetGroup = new elbv2.ApplicationTargetGroup(this, 'TargetGroup', {
48
+ vpc,
49
+ port: 80,
50
+ protocol: elbv2.ApplicationProtocol.HTTP,
51
+ targetType: elbv2.TargetType.IP,
52
+ healthCheck: {
53
+ path: '/health',
54
+ interval: cdk.Duration.seconds(30),
55
+ timeout: cdk.Duration.seconds(5),
56
+ healthyThresholdCount: 2,
57
+ unhealthyThresholdCount: 3,
58
+ },
59
+ });
60
+
61
+ // ALB Listener
62
+ alb.addListener('HttpListener', {
63
+ port: 80,
64
+ protocol: elbv2.ApplicationProtocol.HTTP,
65
+ defaultTargetGroups: [targetGroup],
66
+ });
67
+
68
+ // ECS Task Definition
69
+ const taskDefinition = new ecs.FargateTaskDefinition(this, 'TaskDef', {
70
+ memoryLimitMiB: 1024,
71
+ cpu: 512,
72
+ });
73
+
74
+ // Container Definition
75
+ taskDefinition.addContainer('AppContainer', {
76
+ containerName: 'app',
77
+ image: ecs.ContainerImage.fromRegistry('nginx:latest'),
78
+ portMappings: [
79
+ {
80
+ containerPort: 80,
81
+ protocol: ecs.Protocol.TCP,
82
+ },
83
+ ],
84
+ logging: ecs.LogDrivers.awsLogs({
85
+ streamPrefix: 'app',
86
+ }),
87
+ });
88
+
89
+ // ECS Service
90
+ const service = new ecs.FargateService(this, 'Service', {
91
+ cluster,
92
+ taskDefinition,
93
+ desiredCount: 2,
94
+ assignPublicIp: false,
95
+ securityGroups: [this.appSecurityGroup],
96
+ vpcSubnets: {
97
+ subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
98
+ },
99
+ });
100
+
101
+ // Attach service to target group
102
+ service.attachToApplicationTargetGroup(targetGroup);
103
+
104
+ // Allow ALB to communicate with ECS tasks
105
+ this.appSecurityGroup.addIngressRule(
106
+ ec2.Peer.securityGroupId(alb.connections.securityGroups[0].securityGroupId),
107
+ ec2.Port.tcp(80),
108
+ 'Allow traffic from ALB'
109
+ );
110
+
111
+ // Stack outputs
112
+ new cdk.CfnOutput(this, 'LoadBalancerDNS', {
113
+ value: alb.loadBalancerDnsName,
114
+ description: 'Application Load Balancer DNS name',
115
+ exportName: 'ComputeStack-LoadBalancerDNS',
116
+ });
117
+
118
+ new cdk.CfnOutput(this, 'ClusterName', {
119
+ value: cluster.clusterName,
120
+ description: 'ECS Cluster name',
121
+ });
122
+
123
+ new cdk.CfnOutput(this, 'ServiceName', {
124
+ value: service.serviceName,
125
+ description: 'ECS Service name',
126
+ });
127
+ }
128
+ }
@@ -0,0 +1,69 @@
1
+ import * as cdk from 'aws-cdk-lib';
2
+ import * as ec2 from 'aws-cdk-lib/aws-ec2';
3
+ import { Construct } from 'constructs';
4
+
5
+ /**
6
+ * Networking stack - Foundation layer
7
+ *
8
+ * Creates VPC with public and private subnets, NAT Gateway, and VPC Endpoints
9
+ */
10
+ export class NetworkingStack extends cdk.Stack {
11
+ public readonly vpc: ec2.Vpc;
12
+
13
+ constructor(scope: Construct, id: string, props?: cdk.StackProps) {
14
+ super(scope, id, props);
15
+
16
+ // VPC with public and private subnets across 2 AZs
17
+ this.vpc = new ec2.Vpc(this, 'Vpc', {
18
+ vpcName: 'multi-stack-vpc',
19
+ maxAzs: 2,
20
+ natGateways: 1, // Single NAT Gateway for cost optimization
21
+ subnetConfiguration: [
22
+ {
23
+ name: 'Public',
24
+ subnetType: ec2.SubnetType.PUBLIC,
25
+ cidrMask: 24,
26
+ },
27
+ {
28
+ name: 'Private',
29
+ subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
30
+ cidrMask: 24,
31
+ },
32
+ ],
33
+ });
34
+
35
+ // VPC Endpoint for S3 (Gateway endpoint - no cost)
36
+ this.vpc.addGatewayEndpoint('S3Endpoint', {
37
+ service: ec2.GatewayVpcEndpointAwsService.S3,
38
+ });
39
+
40
+ // VPC Endpoint for DynamoDB (Gateway endpoint - no cost)
41
+ this.vpc.addGatewayEndpoint('DynamoDbEndpoint', {
42
+ service: ec2.GatewayVpcEndpointAwsService.DYNAMODB,
43
+ });
44
+
45
+ // VPC Endpoint for ECR API (Interface endpoint - has cost)
46
+ this.vpc.addInterfaceEndpoint('EcrApiEndpoint', {
47
+ service: ec2.InterfaceVpcEndpointAwsService.ECR,
48
+ privateDnsEnabled: true,
49
+ });
50
+
51
+ // VPC Endpoint for ECR Docker (Interface endpoint - has cost)
52
+ this.vpc.addInterfaceEndpoint('EcrDockerEndpoint', {
53
+ service: ec2.InterfaceVpcEndpointAwsService.ECR_DOCKER,
54
+ privateDnsEnabled: true,
55
+ });
56
+
57
+ // Stack outputs
58
+ new cdk.CfnOutput(this, 'VpcId', {
59
+ value: this.vpc.vpcId,
60
+ description: 'VPC ID',
61
+ exportName: 'NetworkingStack-VpcId',
62
+ });
63
+
64
+ new cdk.CfnOutput(this, 'VpcCidr', {
65
+ value: this.vpc.vpcCidrBlock,
66
+ description: 'VPC CIDR block',
67
+ });
68
+ }
69
+ }