I have a simple CDK application with a backend stack that basically creates an gateway API and configures a cognito workflow for user registration and login using google federation.
In addition, there is a frontend stack which creates a ApplicationLoadBalancedFargateService and loads a NextJS application running as a docker image.
There are two interdependent variables that both stacks need and it has become a catch 22 situation.
The backend stack needs the frontends URL, because it needs to configure the UserPoolClient callback URL
The frontend stack needs the backends RestApi URL for configuring the NextJS env file specifying the fetch URLs.
For production deployment, I already know the domain and api URLs ahead of time ie
www.example.com api.example.com
so it's not an issue, but for staging and development I rely on the outputted URLs generated by AWS.
How can I grab these values during cdk deployment and what's the best way to do this? I am thinking of deploying the frontend first to get the URL, and then feed that to the backend stack as part it's callbackUrl. Then somehow use AppConfig to specify the API url for nextJS to read and use when fetching data. Is this a good approach?
As you say, the CDK can't deploy the app if each stack depends upon the other. One way to remove the cyclic dependency is to add an event-triggered Lambda to the Backend Stack. The Lambda sets the Callback URL whenever the Frontend Stack deploys.
parameterName
. Set its value to the NextJS URL your backend needs for the callback URL.To make this work, the Backend Stack just needs to know the Frontend Stack's stack name (for the event rule) and the name of the parameter where the Frontend Stack has stored the callback URL.
Note: Alternatively, it might be possible to add Step 4's Lambda to the Frontend Stack as a Custom Resource. This would be a pure CloudFormation solution without a need for Step 3's event logic. The Frontend Stack would need to know the Cognito ClientId. The big disadvantage woud be that the Frontend Stack would be modifiying a Backend Stack resource, introducing cross-stack mingling of concerns. The above event-driven solution maintains better separation of concerns.