diff --git a/infrastructure/terraform/modules/lambda/README.md b/infrastructure/terraform/modules/lambda/README.md
index d09e623a..08775969 100644
--- a/infrastructure/terraform/modules/lambda/README.md
+++ b/infrastructure/terraform/modules/lambda/README.md
@@ -20,7 +20,7 @@
| [enable\_lambda\_insights](#input\_enable\_lambda\_insights) | Enable the lambda insights layer, this must be disabled for lambda@edge usage | `bool` | `true` | no |
| [environment](#input\_environment) | The name of the tfscaffold environment | `string` | n/a | yes |
| [filter\_pattern](#input\_filter\_pattern) | Filter pattern to use for the log subscription filter | `string` | `""` | no |
-| [force\_lambda\_code\_deploy](#input\_force\_lambda\_code\_deploy) | If the lambda package in s3 has the same commit id tag as the terraform build branch, the lambda will not update automatically. Set to True if making changes to Lambda code from on the same commit for example during development | `bool` | `false` | no |
+| [force\_lambda\_code\_deploy](#input\_force\_lambda\_code\_deploy) | If true, force code deploy checks for Lambda packages. For Zip, this enables source hash tracking of the package archive. For Image, tagged ECR image URIs are resolved to their current digest so Lambda updates when the tag is repointed. | `bool` | `false` | no |
| [function\_code\_base\_path](#input\_function\_code\_base\_path) | The base path to the sourcecode directories needed for this lambda | `string` | `"./"` | no |
| [function\_code\_dir](#input\_function\_code\_dir) | The directory for this lambda | `string` | `null` | no |
| [function\_include\_common](#input\_function\_include\_common) | Include the 'common' lambda module with this lambda | `bool` | `true` | no |
diff --git a/infrastructure/terraform/modules/lambda/data_ecr_image_lambda.tf b/infrastructure/terraform/modules/lambda/data_ecr_image_lambda.tf
new file mode 100644
index 00000000..e0cf4cfe
--- /dev/null
+++ b/infrastructure/terraform/modules/lambda/data_ecr_image_lambda.tf
@@ -0,0 +1,6 @@
+data "aws_ecr_image" "lambda" {
+ count = local.resolve_image_to_digest ? 1 : 0
+
+ repository_name = local.image_repository_name
+ image_tag = local.image_tag
+}
diff --git a/infrastructure/terraform/modules/lambda/lambda_function.tf b/infrastructure/terraform/modules/lambda/lambda_function.tf
index f67849a5..118ff3b7 100644
--- a/infrastructure/terraform/modules/lambda/lambda_function.tf
+++ b/infrastructure/terraform/modules/lambda/lambda_function.tf
@@ -13,7 +13,7 @@ resource "aws_lambda_function" "main" {
s3_key = local.package_type == "zip" ? aws_s3_object.lambda[0].key : null
s3_object_version = local.package_type == "zip" ? aws_s3_object.lambda[0].version_id : null
- image_uri = local.package_type == "image" ? var.image_uri : null
+ image_uri = local.package_type == "image" ? local.effective_image_uri : null
dynamic "image_config" {
for_each = local.package_type == "image" && var.image_config != null ? [1] : []
diff --git a/infrastructure/terraform/modules/lambda/locals.tf b/infrastructure/terraform/modules/lambda/locals.tf
index bd112a02..0cc66246 100644
--- a/infrastructure/terraform/modules/lambda/locals.tf
+++ b/infrastructure/terraform/modules/lambda/locals.tf
@@ -3,6 +3,18 @@ locals {
package_type = lower(var.package_type)
+ # For Image package types, optionally resolve tag-based URIs to digests
+ # when force_lambda_code_deploy is enabled.
+ image_uri_parts = split(":", var.image_uri != null ? var.image_uri : "")
+ image_uri_has_digest = var.image_uri != null ? length(split("@", var.image_uri)) > 1 : false
+ image_uri_has_tag = var.image_uri != null ? length(local.image_uri_parts) == 2 : false
+ image_repository_uri = local.image_uri_has_tag ? local.image_uri_parts[0] : null
+ image_tag = local.image_uri_has_tag ? local.image_uri_parts[1] : null
+ image_repository_parts = local.image_repository_uri != null ? split("/", local.image_repository_uri) : []
+ image_repository_name = local.image_repository_uri != null ? join("/", slice(local.image_repository_parts, 1, length(local.image_repository_parts))) : null
+ resolve_image_to_digest = local.package_type == "image" && var.force_lambda_code_deploy && !local.image_uri_has_digest && local.image_uri_has_tag
+ effective_image_uri = local.resolve_image_to_digest ? "${local.image_repository_uri}@${data.aws_ecr_image.lambda[0].image_digest}" : var.image_uri
+
# Compound Scope Identifier
csi = replace(
format(
diff --git a/infrastructure/terraform/modules/lambda/variables.tf b/infrastructure/terraform/modules/lambda/variables.tf
index ed335f94..815d43be 100644
--- a/infrastructure/terraform/modules/lambda/variables.tf
+++ b/infrastructure/terraform/modules/lambda/variables.tf
@@ -198,7 +198,7 @@ variable "function_include_common" {
variable "force_lambda_code_deploy" {
type = bool
- description = "If the lambda package in s3 has the same commit id tag as the terraform build branch, the lambda will not update automatically. Set to True if making changes to Lambda code from on the same commit for example during development"
+ description = "If true, force code deploy checks for Lambda packages. For Zip, this enables source hash tracking of the package archive. For Image, tagged ECR image URIs are resolved to their current digest so Lambda updates when the tag is repointed."
default = false
}