From 7e5ebe5dc758f8795ac9666464e7c36cda867c51 Mon Sep 17 00:00:00 2001 From: Pavel Tcholakov Date: Tue, 5 May 2026 21:38:05 +0200 Subject: [PATCH] Fix ServiceDeployer LogGroup conflict with useCdkManagedLogGroup feature flag When the @aws-cdk/aws-lambda:useCdkManagedLogGroup feature flag is enabled (recommended default since CDK 2.200.0), the Lambda construct automatically creates a CloudFormation LogGroup. ServiceDeployer was creating a second one with the same name, causing a conflict during deployment. Fix: check the feature flag via cdk.FeatureFlags before creating the explicit LogGroup. Users who want custom retention with the flag enabled can pass a logGroup via props (already supported). Fixes #90 --- lib/restate-constructs/service-deployer.ts | 6 +++++- test/restate-constructs.test.ts | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/restate-constructs/service-deployer.ts b/lib/restate-constructs/service-deployer.ts index 6eac279..4d8e7b6 100644 --- a/lib/restate-constructs/service-deployer.ts +++ b/lib/restate-constructs/service-deployer.ts @@ -12,6 +12,7 @@ import path from "node:path"; import { Construct } from "constructs"; import * as cdk from "aws-cdk-lib"; +import * as cx_api from "aws-cdk-lib/cx-api"; import * as iam from "aws-cdk-lib/aws-iam"; import * as lambda from "aws-cdk-lib/aws-lambda"; import * as lambda_node from "aws-cdk-lib/aws-lambda-nodejs"; @@ -219,7 +220,10 @@ export class ServiceDeployer extends Construct { allowPublicSubnet: props?.allowPublicSubnet, }); - if (!props?.logGroup) { + // Skip creating an explicit LogGroup when CDK manages it automatically via the + // useCdkManagedLogGroup feature flag - both would resolve to the same name and conflict. + const cdkManagedLogGroup = cdk.FeatureFlags.of(this).isEnabled(cx_api.USE_CDK_MANAGED_LAMBDA_LOGGROUP); + if (!props?.logGroup && !cdkManagedLogGroup) { // By default, Lambda Functions have a log group with never-expiring retention policy. new logs.LogGroup(this, "DeploymentLogs", { logGroupName: `/aws/lambda/${this.eventHandler.functionName}`, diff --git a/test/restate-constructs.test.ts b/test/restate-constructs.test.ts index fa4cf9d..26b412a 100644 --- a/test/restate-constructs.test.ts +++ b/test/restate-constructs.test.ts @@ -117,6 +117,26 @@ describe("Restate constructs", () => { }); }); + test("ServiceDeployer with useCdkManagedLogGroup feature flag enabled", () => { + const app = new cdk.App({ + context: { "@aws-cdk/aws-lambda:useCdkManagedLogGroup": true }, + }); + const stack = new cdk.Stack(app, "RestateCloudStack", { + env: { account: "account-id", region: "region" }, + }); + + new ServiceDeployer(stack, "ServiceDeployer", { + code: lambda.Code.fromAsset("dist/register-service-handler"), + }); + + const template = app.synth().getStackByName("RestateCloudStack").template; + const logGroups = Object.values(template.Resources as Record).filter( + (r) => r.Type === "AWS::Logs::LogGroup", + ); + // Only the CDK-managed LogGroup created by the Lambda construct; none added by ServiceDeployer + expect(logGroups).toHaveLength(1); + }); + test("Service Deployer overrides", () => { const app = new cdk.App(); const stack = new cdk.Stack(app, "RestateCloudStack", {