diff --git a/infrastructure/modules/relay-hybrid-connection/README.md b/infrastructure/modules/relay-hybrid-connection/README.md
new file mode 100644
index 00000000..d5022dc0
--- /dev/null
+++ b/infrastructure/modules/relay-hybrid-connection/README.md
@@ -0,0 +1,126 @@
+# relay-hybrid-connection
+
+Deploy an [Azure Relay Hybrid Connection](https://learn.microsoft.com/en-us/azure/azure-relay/relay-hybrid-connections-protocol) to enable secure, bi-directional communication between on-premises applications and Azure services through an existing Azure Relay namespace.
+
+This module creates:
+- Azure Relay Hybrid Connection
+- Optional authorization rules with configurable permissions (Listen, Send, Manage)
+
+**Note:** This module requires an existing Azure Relay namespace. Use the `relay-namespace` module to create the namespace first.
+
+## Terraform documentation
+For the list of inputs, outputs, resources... check the [terraform module documentation](tfdocs.md).
+
+## Usage
+
+### Basic usage (without authorization rules)
+```hcl
+module "relay_hybrid_connection" {
+ source = "../../../dtos-devops-templates/infrastructure/modules/relay-hybrid-connection"
+
+ name = "hc-${var.application}-${var.environment}"
+ relay_namespace_name = module.relay_namespace.name
+ resource_group_name = var.resource_group_name
+}
+```
+
+### With authorization rules
+```hcl
+module "relay_hybrid_connection" {
+ source = "../../../dtos-devops-templates/infrastructure/modules/relay-hybrid-connection"
+
+ name = "hc-${var.application}-${var.environment}"
+ relay_namespace_name = module.relay_namespace.name
+ resource_group_name = var.resource_group_name
+ requires_client_authorization = true
+ user_metadata = "Application hybrid connection"
+
+ authorization_rules = {
+ "listen-rule" = {
+ listen = true
+ send = false
+ manage = false
+ }
+ "send-rule" = {
+ listen = false
+ send = true
+ manage = false
+ }
+ "manage-rule" = {
+ listen = true
+ send = true
+ manage = true
+ }
+ }
+}
+```
+
+### Complete example with namespace
+```hcl
+# Create the relay namespace first
+module "relay_namespace" {
+ source = "../../../dtos-devops-templates/infrastructure/modules/relay-namespace"
+
+ name = "relay-${var.application}-${var.environment}"
+ resource_group_name = var.resource_group_name
+ location = var.location
+ log_analytics_workspace_id = data.terraform_remote_state.audit.outputs.log_analytics_workspace_id
+
+ tags = var.tags
+}
+
+# Create hybrid connection with authorization rules
+module "relay_hybrid_connection" {
+ source = "../../../dtos-devops-templates/infrastructure/modules/relay-hybrid-connection"
+
+ name = "hc-${var.application}-${var.environment}"
+ relay_namespace_name = module.relay_namespace.name
+ resource_group_name = var.resource_group_name
+
+ authorization_rules = {
+ "app-listener" = {
+ listen = true
+ }
+ "app-sender" = {
+ send = true
+ }
+ }
+}
+```
+
+## Naming constraints
+
+The Azure Relay Hybrid Connection name must follow these rules:
+
+| Constraint | Requirement |
+|------------|-------------|
+| Length | 1-260 characters |
+| Start | Must start with a letter or number |
+| End | Must end with a letter or number |
+| Characters | Letters, numbers, hyphens, underscores, and periods |
+
+Authorization rule names follow similar constraints (1-256 characters).
+
+## Authorization rules
+
+Authorization rules support three permission types:
+
+| Permission | Description |
+|------------|-------------|
+| `listen` | Allows receiving messages from the hybrid connection |
+| `send` | Allows sending messages to the hybrid connection |
+| `manage` | Allows managing the hybrid connection (requires both `listen` and `send` to be `true`) |
+
+**Note:** When `manage = true`, both `listen` and `send` must also be set to `true`. The module validates this constraint.
+
+## Outputs
+
+| Output | Description |
+|--------|-------------|
+| `name` | The name of the Hybrid Connection |
+| `id` | The resource ID of the Hybrid Connection |
+| `authorization_rule_ids` | Map of authorization rule names to their IDs |
+| `authorization_rule_primary_keys` | Map of authorization rule names to their primary keys (sensitive) |
+| `authorization_rule_secondary_keys` | Map of authorization rule names to their secondary keys (sensitive) |
+| `authorization_rule_primary_connection_strings` | Map of authorization rule names to their primary connection strings (sensitive) |
+| `authorization_rule_secondary_connection_strings` | Map of authorization rule names to their secondary connection strings (sensitive) |
diff --git a/infrastructure/modules/relay-hybrid-connection/main.tf b/infrastructure/modules/relay-hybrid-connection/main.tf
new file mode 100644
index 00000000..f5ec5b97
--- /dev/null
+++ b/infrastructure/modules/relay-hybrid-connection/main.tf
@@ -0,0 +1,26 @@
+/* --------------------------------------------------------------------------------------------------
+ Azure Relay Hybrid Connection
+-------------------------------------------------------------------------------------------------- */
+resource "azurerm_relay_hybrid_connection" "hybrid_connection" {
+ name = var.name
+ relay_namespace_name = var.relay_namespace_name
+ resource_group_name = var.resource_group_name
+ requires_client_authorization = var.requires_client_authorization
+ user_metadata = var.user_metadata
+}
+
+/* --------------------------------------------------------------------------------------------------
+ Azure Relay Hybrid Connection Authorization Rules
+-------------------------------------------------------------------------------------------------- */
+resource "azurerm_relay_hybrid_connection_authorization_rule" "auth_rule" {
+ for_each = var.authorization_rules
+
+ name = each.key
+ hybrid_connection_name = azurerm_relay_hybrid_connection.hybrid_connection.name
+ namespace_name = var.relay_namespace_name
+ resource_group_name = var.resource_group_name
+
+ listen = each.value.listen
+ send = each.value.send
+ manage = each.value.manage
+}
diff --git a/infrastructure/modules/relay-hybrid-connection/output.tf b/infrastructure/modules/relay-hybrid-connection/output.tf
new file mode 100644
index 00000000..6fed148b
--- /dev/null
+++ b/infrastructure/modules/relay-hybrid-connection/output.tf
@@ -0,0 +1,38 @@
+output "id" {
+ description = "The ID of the Relay Hybrid Connection."
+ value = azurerm_relay_hybrid_connection.hybrid_connection.id
+}
+
+output "name" {
+ description = "The name of the Relay Hybrid Connection."
+ value = azurerm_relay_hybrid_connection.hybrid_connection.name
+}
+
+output "authorization_rule_ids" {
+ description = "A map of authorization rule names to their IDs."
+ value = { for k, v in azurerm_relay_hybrid_connection_authorization_rule.auth_rule : k => v.id }
+}
+
+output "authorization_rule_primary_keys" {
+ description = "A map of authorization rule names to their primary keys."
+ value = { for k, v in azurerm_relay_hybrid_connection_authorization_rule.auth_rule : k => v.primary_key }
+ sensitive = true
+}
+
+output "authorization_rule_secondary_keys" {
+ description = "A map of authorization rule names to their secondary keys."
+ value = { for k, v in azurerm_relay_hybrid_connection_authorization_rule.auth_rule : k => v.secondary_key }
+ sensitive = true
+}
+
+output "authorization_rule_primary_connection_strings" {
+ description = "A map of authorization rule names to their primary connection strings."
+ value = { for k, v in azurerm_relay_hybrid_connection_authorization_rule.auth_rule : k => v.primary_connection_string }
+ sensitive = true
+}
+
+output "authorization_rule_secondary_connection_strings" {
+ description = "A map of authorization rule names to their secondary connection strings."
+ value = { for k, v in azurerm_relay_hybrid_connection_authorization_rule.auth_rule : k => v.secondary_connection_string }
+ sensitive = true
+}
diff --git a/infrastructure/modules/relay-hybrid-connection/tfdocs.md b/infrastructure/modules/relay-hybrid-connection/tfdocs.md
new file mode 100644
index 00000000..5ccc9f89
--- /dev/null
+++ b/infrastructure/modules/relay-hybrid-connection/tfdocs.md
@@ -0,0 +1,97 @@
+# Module documentation
+
+## Required Inputs
+
+The following input variables are required:
+
+### [name](#input\_name)
+
+Description: The name of the Azure Relay Hybrid Connection.
+
+Type: `string`
+
+### [relay\_namespace\_name](#input\_relay\_namespace\_name)
+
+Description: The name of the Azure Relay namespace in which to create the Hybrid Connection.
+
+Type: `string`
+
+### [resource\_group\_name](#input\_resource\_group\_name)
+
+Description: The name of the resource group containing the Azure Relay namespace.
+
+Type: `string`
+
+## Optional Inputs
+
+The following input variables are optional (have default values):
+
+### [authorization\_rules](#input\_authorization\_rules)
+
+Description: A map of authorization rules to create for the Hybrid Connection.
+
+Type:
+
+```hcl
+map(object({
+ listen = optional(bool, false)
+ send = optional(bool, false)
+ manage = optional(bool, false)
+ }))
+```
+
+Default: `{}`
+
+### [requires\_client\_authorization](#input\_requires\_client\_authorization)
+
+Description: Whether client authorization is required for this Hybrid Connection.
+
+Type: `bool`
+
+Default: `true`
+
+### [user\_metadata](#input\_user\_metadata)
+
+Description: User metadata string for the Hybrid Connection.
+
+Type: `string`
+
+Default: `null`
+
+## Outputs
+
+The following outputs are exported:
+
+### [authorization\_rule\_ids](#output\_authorization\_rule\_ids)
+
+Description: A map of authorization rule names to their IDs.
+
+### [authorization\_rule\_primary\_connection\_strings](#output\_authorization\_rule\_primary\_connection\_strings)
+
+Description: A map of authorization rule names to their primary connection strings.
+
+### [authorization\_rule\_primary\_keys](#output\_authorization\_rule\_primary\_keys)
+
+Description: A map of authorization rule names to their primary keys.
+
+### [authorization\_rule\_secondary\_connection\_strings](#output\_authorization\_rule\_secondary\_connection\_strings)
+
+Description: A map of authorization rule names to their secondary connection strings.
+
+### [authorization\_rule\_secondary\_keys](#output\_authorization\_rule\_secondary\_keys)
+
+Description: A map of authorization rule names to their secondary keys.
+
+### [id](#output\_id)
+
+Description: The ID of the Relay Hybrid Connection.
+
+### [name](#output\_name)
+
+Description: The name of the Relay Hybrid Connection.
+## Resources
+
+The following resources are used by this module:
+
+- [azurerm_relay_hybrid_connection.hybrid_connection](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/relay_hybrid_connection) (resource)
+- [azurerm_relay_hybrid_connection_authorization_rule.auth_rule](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/relay_hybrid_connection_authorization_rule) (resource)
diff --git a/infrastructure/modules/relay-hybrid-connection/variables.tf b/infrastructure/modules/relay-hybrid-connection/variables.tf
new file mode 100644
index 00000000..7cf17c6a
--- /dev/null
+++ b/infrastructure/modules/relay-hybrid-connection/variables.tf
@@ -0,0 +1,56 @@
+variable "name" {
+ description = "The name of the Azure Relay Hybrid Connection."
+ type = string
+ validation {
+ condition = can(regex("^[a-zA-Z0-9]([a-zA-Z0-9-._]{0,258}[a-zA-Z0-9])?$", var.name))
+ error_message = "The hybrid connection name must be 1-260 characters, start and end with an alphanumeric character, and can only contain letters, numbers, hyphens, underscores, and periods."
+ }
+}
+
+variable "relay_namespace_name" {
+ description = "The name of the Azure Relay namespace in which to create the Hybrid Connection."
+ type = string
+}
+
+variable "resource_group_name" {
+ description = "The name of the resource group containing the Azure Relay namespace."
+ type = string
+}
+
+variable "requires_client_authorization" {
+ description = "Whether client authorization is required for this Hybrid Connection."
+ type = bool
+ default = true
+}
+
+variable "user_metadata" {
+ description = "User metadata string for the Hybrid Connection."
+ type = string
+ default = null
+}
+
+variable "authorization_rules" {
+ description = "A map of authorization rules to create for the Hybrid Connection."
+ type = map(object({
+ listen = optional(bool, false)
+ send = optional(bool, false)
+ manage = optional(bool, false)
+ }))
+ default = {}
+
+ validation {
+ condition = alltrue([
+ for name, rule in var.authorization_rules :
+ can(regex("^[a-zA-Z0-9]([a-zA-Z0-9-._]{0,254}[a-zA-Z0-9])?$", name))
+ ])
+ error_message = "Authorization rule names must be 1-256 characters, start and end with an alphanumeric character, and can only contain letters, numbers, hyphens, underscores, and periods."
+ }
+
+ validation {
+ condition = alltrue([
+ for name, rule in var.authorization_rules :
+ rule.manage == false || (rule.listen == true && rule.send == true)
+ ])
+ error_message = "When 'manage' is true, both 'listen' and 'send' must also be true."
+ }
+}
diff --git a/infrastructure/modules/relay-namespace/README.md b/infrastructure/modules/relay-namespace/README.md
index dfd20b6a..7c6d72a0 100644
--- a/infrastructure/modules/relay-namespace/README.md
+++ b/infrastructure/modules/relay-namespace/README.md
@@ -7,7 +7,7 @@ This module creates:
- Optional private endpoint for secure connectivity
- Diagnostic settings for monitoring and logging
-**Note:** This module only creates the namespace. Hybrid connections and authorization rules should be created separately using dedicated modules to support the pattern of one namespace with many hybrid connections.
+**Note:** This module only creates the namespace. Hybrid connections and authorization rules should be created separately using the [relay-hybrid-connection](../relay-hybrid-connection/README.md) module to support the pattern of one namespace with many hybrid connections.
## Private DNS Zone