3

recently started working on a CDK project, Wanted to have views of y'all on how to structure it. Ill lay out what I have thought.

Will be have 2 separate packages.

  1. ApplicationCommonsPackage
  2. SpecificApplicationCDKPackage(Can be many such packages), These will depend on the ApplicationCommonsPackage

The ApplicationCommonsPackage will hold all the common logic for all our applications(till now have thought of Configs, Common constructs, factory method for creating constructs)

The latter(SpecificApplicationCDKPackage) will hold configs for the constructs and will use the factory in ApplicationCommonsPackage for creating stuff.

What do you think of using factory pattern in ApplicationCommonsPackage? One issue I am facing is that I cannot expose a common interface with a generic method(or am not able to?) for the factory. The reason being every construct requires props which are of very specific type, I cannot generalise them to any or such sort as by that will lose the niceness of typescript. So am having functions like createLambda(scope: Stack, id: string, props: LambdaProps): Function in my factory. I am not liking this structure a lot, I would have loved generic function which took the Function as an input and would have determined the type of props from it. Something like create<T>(scope: Stack, id: string, props: <U derived from T => some methodology to get this?>): T so that when I actually use this in SpecificApplicationCDKPackage like so - this.factory.create<Function>(this, 'SampleLambda', {}) I get all compile time errors for the props parameter({})

Michelle
  • 97
  • 1
  • 10
  • I suggest asking your typescript question separately. Its straightforward generics-related language details are distinct from whether the factory pattern is a good solution to your CDK question. – rob3c Sep 08 '21 at 04:56

1 Answers1

3

While working with aws-cdk it is important to keep in mind how we gather resources into Stacks. Once you put a resource into a cdk Stack, which then maps to CloudFormation Stack, it may be more involved to move it to a different stack after an initial production deployment.

The best way to decide if two resources should be in the same stack is to apply module design heuristic. In other words it is better if resources have more coupling within a Stack (module) than across different Stacks (modules).

For example we very often have a database (e.g. RDS) and some service connecting to it. The service when communicating with database needs its hostname, username, password and the database needs to allow that on the AWS Security Group level. Thus the number of references between a service and database is high and they should likely live inside single module (CDK Stack).

On the other side, if we have 2 services, which communicate with each other via http then one service may only need to know other service DNS name. In such case the 2 services may be better suited to live in separate Stacks.

We obviously can have helper libraries that aid creating common constructs. However, it is important to remember that objects constructed in cdk map to AWS resources. Once CDK app is deployed an innocent looking refactoring may result in resources being replaced in subsequent deploys.

miensol
  • 39,733
  • 7
  • 116
  • 112
  • Hi @miensol, agree with your points. Are there any good resources for "module design heuristic". I would love to read more on it. Thanks – Michelle May 31 '21 at 08:17
  • Hi, I also was wondering if I may require to use the same vpc(for e.g.) across stacks? Especially as vpc has such a tight limitation of 5 per region and I don't want to create new vpcs for every `SpecificApplicationCDKPackage`. Do you know if this is a common practice or is recommended or not? – Michelle May 31 '21 at 11:12
  • 1
    I'd recommend having separate stack for network i.e. VPC and related. You can then pass the IVpc reference around. The network will rarely change thus it's not a big deal to have those references passed around. You can have many more than 5 VPCs but then in order to connect them you'll need to either go through internet or through VPC Peering. If your organisation isn't big I guess starting with a single VPC per deployment environment (stage, qa, prod) is the way to go. – miensol May 31 '21 at 15:41
  • Hi, sorry if I was not clear, what I meant was to have a vpc stack defined in `ApplicationCommonsPackage` and use the same vpc in all the `SpecificApplicationCDKPackage`. From what I know it will be 2 separate apps which will hold the vpcStack and the specificStack right? so is it possible to still pass IVpc to `SpecificApplicationCDKPackage` from `ApplicationCommonsPackage`? – Michelle May 31 '21 at 20:08
  • IMHO it's possible to setup even though [some claim it may not be](https://stackoverflow.com/questions/65341642/aws-cdk-multiple-apps). However, it will require understanding the abstractions which sit behind CDK. AFAIK an app in CDK is a collection of CF stacks. If your multiple apps will share some physical stack (e.g. NetworkStack) referencing it around should work in theory. There are some risks involved though. E.g. changing the network stack definition while deploying app1 and reverting/changing that definition when deploying app2. – miensol Jun 04 '21 at 06:19