Elastic Load Balancing v2
Protocol: Query (XML) — POST http://localhost:4566/ with Action= parameter
Floci supports Application Load Balancers (ALB) and Network Load Balancers (NLB) through the ELBv2 management API. The control plane is AWS SDK / CLI / Terraform compatible. HTTP, HTTPS, and TCP listeners can forward to registered instance and IP targets using the target's reachable local address.
Classic (v1) Elastic Load Balancing is a different API served from the same endpoint host — see ELB Classic (v1). Requests are routed by their
Versionparameter:2015-12-01here,2012-06-01there.
Supported Actions
Load Balancers
| Action | Description |
|---|---|
| CreateLoadBalancer | Creates an ALB or NLB in active state with persisted attributes and tags. |
| DescribeLoadBalancers | Lists or returns stored load balancers. |
| DeleteLoadBalancer | Deletes a load balancer and stops its listener sockets. |
| ModifyLoadBalancerAttributes | Updates persisted load balancer attributes. |
| DescribeLoadBalancerAttributes | Returns attributes stored for a load balancer. |
| DescribeCapacityReservation | Returns the stored capacity reservation fields for a load balancer. |
| SetSecurityGroups | Replaces the security groups associated with a load balancer. |
| SetSubnets | Replaces the subnets associated with a load balancer. |
| SetIpAddressType | Updates the IP address type stored for a load balancer. |
Target Groups
| Action | Description |
|---|---|
| CreateTargetGroup | Creates a target group with protocol, port, health check, and target-type settings. |
| DescribeTargetGroups | Lists or returns stored target groups. |
| ModifyTargetGroup | Updates mutable target group settings. |
| DeleteTargetGroup | Deletes an unused target group. |
| ModifyTargetGroupAttributes | Updates persisted target group attributes. |
| DescribeTargetGroupAttributes | Returns attributes stored for a target group. |
Targets
| Action | Description |
|---|---|
| RegisterTargets | Registers targets with a target group. |
| DeregisterTargets | Removes targets from a target group. |
| DescribeTargetHealth | Returns target health records maintained by Floci. |
Listeners
HTTPS listeners require a default certificate. Supply one when creating a listener or changing an HTTP listener to HTTPS; an omitted certificate list on an existing HTTPS listener keeps its default.
Listener responses omit Certificates when the listener has none. Configured certificates
remain present in create, describe and modify responses.
Creating an HTTPS or TLS listener without SslPolicy selects ELBSecurityPolicy-2016-08,
matching AWS's default for API, CLI and CloudFormation creation. An explicit policy
is preserved, and omitting the policy on subsequent modifications retains its current
value. These policies remain present in create, describe and modify responses;
listeners with no policy, such as HTTP listeners, omit SslPolicy.
Changing HTTPS to HTTP or TLS to TCP removes the SSL policy and certificate configuration. Changing HTTP to HTTPS or TCP to TLS requires an explicit SSL policy and default certificate; missing either rejects the modification without changing the listener. Changing other properties without changing protocol retains the existing security settings.
Gateway Load Balancer listeners require omitted Port and Protocol fields on both create and modify requests. Their portless control-plane configuration does not provide GENEVE packet forwarding.
| Action | Description |
|---|---|
| CreateListener | Creates a listener and its non-deletable default rule. |
| DescribeListeners | Lists or returns stored listeners. |
| ModifyListener | Updates a listener's configuration and default actions. |
| ModifyListenerAttributes | Updates persisted listener attributes. |
| DescribeListenerAttributes | Returns attributes stored for a listener. |
| DeleteListener | Deletes a listener and stops its socket. |
| AddListenerCertificates | Adds certificates to a listener. |
| RemoveListenerCertificates | Removes certificates from a listener. |
| DescribeListenerCertificates | Lists certificates associated with a listener. |
Rules
| Action | Description |
|---|---|
| CreateRule | Creates a non-default listener rule with conditions, actions, and priority. |
| DescribeRules | Lists or returns listener rules. |
| ModifyRule | Updates a listener rule's conditions and actions. |
| DeleteRule | Deletes a non-default listener rule. |
| SetRulePriorities | Atomically updates rule priorities after validating uniqueness. |
Tags
| Action | Description |
|---|---|
| AddTags | Adds tags to supported ELBv2 resources. |
| RemoveTags | Removes tags from supported ELBv2 resources. |
| DescribeTags | Returns tags for supported ELBv2 resources. |
Metadata
| Action | Description |
|---|---|
| DescribeSSLPolicies | Returns Floci's pre-seeded standard SSL policy list. |
| DescribeAccountLimits | Returns standard default ELBv2 account limits. |
Behavior Notes
DescribeLoadBalancers,DescribeTargetGroups,DescribeListeners,DescribeRules,DescribeAccountLimitsandDescribeListenerCertificatesreturn their complete matching results without aNextMarker. These handlers do not yet split results usingPageSizeor resume fromMarker.- HTTP and HTTPS target groups use their configured protocol for both application requests and WebSocket upgrades. An HTTPS target requires a TLS handshake; a failed handshake never falls back to plaintext. Backend certificates may be self-signed or expired, as on AWS ALB. This trust setting applies only to the target clients and health checks.
- Backend connection and TLS handshake errors return 502 for HTTP requests and WebSocket upgrades. Connection and handshake timeouts use ten-second deadlines and return 504.
- HTTP and HTTPS health checks use their own configured protocol and port, independently of the target's application protocol. HTTPS health checks require a TLS handshake, preserve the configured success-code matcher, and do not follow redirects.
- One health-check deadline covers connection, TLS handshake and response headers.
Partial bytes do not renew it. Expiry closes the probe and counts toward
Target.Timeout. - Health probes connect directly without JVM proxy settings. A timed-out lookup keeps its target and shared worker slot until the underlying work actually exits. This bounds background work even when name resolution ignores interruption.
- Backend TLS uses the runtime's supported protocols and ciphers. Floci does not reproduce AWS ALB's backend security-policy selection from the frontend listener policy.
- ALB listeners share the emulator's network address. Stored subnet and security-group associations do not create a load-balancer VPC network boundary or enforce frontend ingress and backend egress rules. These listeners cannot yet reproduce NAT allowlisting failures.
- TCP listeners relay bytes bidirectionally without parsing HTTP or terminating TLS. TLS passthrough requires a TCP listener, with certificates configured at the target, not at the listener. Targets are selected per connection using round-robin among healthy targets, falling back to registered targets when none are healthy. The default TCP idle timeout is 350 seconds, configurable via the
tcp.idle_timeout.secondslistener attribute (60 to 6000 seconds). - TCP listeners require a dedicated local port. Floci still shares its address across load balancers, so a second listener on an in-use TCP port registers successfully and logs a warning, but serves no traffic until the listener holding the port is deleted or moved, and ports reserved by Floci remain unavailable. Address isolation and TLS-terminating NLB listeners are not provided by the TCP proxy.
- An asynchronous socket-bind failure retains the admitted listeners and retries while they remain configured. Retry delays grow from 100 milliseconds to five seconds; a successful bind resets the delay. Deleting the last listener or stopping Floci cancels its retry. An external process holding the port must still release it before Floci can serve traffic.
- HTTPS listeners terminate TLS using the configured ACM or IAM server certificates, with SNI certificate selection. When several load balancers share one local HTTPS port, clients must send SNI to identify the certificate they need; a connection without SNI cannot identify a particular load balancer before the TLS handshake.
- ACM certificates must be issued before attaching them. Reimporting an attached ACM certificate refreshes subsequent full TLS handshakes; existing connections keep their negotiated certificate. Reload does not invalidate TLS session caches: a resumed session can retain its previously authenticated certificate after replacement or removal until the session expires or is invalidated. ACM deletion and revocation are refused while a listener still references the certificate.
- Certificate replacement keeps the previous key material available to new handshakes while the replacement loads. A failed reload leaves the previous certificate active.
- Unusable saved listeners are retained for correction and logged individually so other saved listeners can start.
- HTTP or HTTPS listeners sharing a local port must use the same protocol. Requests select a load balancer by its DNS name, a hostname declared by its rules, or a certificate hostname; ambiguous hostnames return 502. TCP never serves a port alongside either protocol; see the TCP note above.
- Load balancer, target group, listener, rule, and tag state is persisted through Floci storage and rebuilt on service startup.
- Load balancers are created in
activestate. CreateLoadBalancertakesSubnetsorSubnetMappingsfor every load balancer type, and both together are refused withValidationError. An Application Load Balancer takes at least two: with one or none it returnsValidationErrorAt least two subnets in two different Availability Zones must be specifiedand creates nothing. The count comes before any subnet is looked up, as on AWS, so one subnet that does not exist gets that error too. A Network or Gateway Load Balancer with neither returnsValidationErrorAt least one subnet must be specified. CloudFormation refuses such anAWS::ElasticLoadBalancingV2::LoadBalancerthe same way when it creates or replaces the balancer; an update that keeps the balancer and names no subnets leaves it on its subnets.SetSubnets, likeCreateLoadBalancer, takesSubnetsorSubnetMappings, and both together are refused withValidationError. With neither it returns the sameValidationErrorasCreateLoadBalancerfor the balancer's type,At least two subnets in two different Availability Zones must be specifiedfor an Application Load Balancer andAt least one subnet must be specifiedfor a Network or Gateway Load Balancer, and leaves the balancer on its subnets. ASetSubnetsthat names subnets is counted asCreateLoadBalancercounts them, following the two-zone rule its API reference states: one subnet for an Application Load Balancer, inSubnetsorSubnetMappings, returnsValidationErrorAt least two subnets in two different Availability Zones must be specifiedbefore any subnet is looked up, and leaves the balancer on its subnets. AWS does not document the error for this case, so Floci givesCreateLoadBalancer's error, in the same order. A CloudFormation update that keeps an Application Load Balancer and names one subnet fails with that error and rolls back. A Network Load Balancer can be set onto one subnet. TheSetSubnetsAPI reference requires a Gateway Load Balancer'sSubnetsto include every subnet it is already on; Floci does not enforce that.- EC2 refuses deletion of subnets and VPCs still referenced by load balancers with
DependencyViolation. These account- and region-scoped dependencies follow persisted load balancer state; changing subnets or deleting the load balancer releases its old references. A CloudFormation update that names other subnets inSubnetsorSubnetMappingsmoves the load balancer the waySetSubnetsdoes, and a rolled-back update moves it back. An independent target group does not prevent subnet or VPC deletion. - HTTP listener sockets are preserved when listener actions change and are restarted only when socket-level settings such as port change.
- Gateway listeners require
ProtocolandPortto be omitted on create and modify. Their control-plane response reportsGENEVEwithout a port. CloudFormation preserves omitted gateway listener settings on create and update; other load balancer types retain their existingHTTPand port 80 defaults. - Instance targets are resolved through EC2 instance private addresses so local load balancer traffic can reach containers.
- Target health starts in
initialstate with reasonElb.RegistrationInProgressand is updated by Floci's health checker when monitoring is active. - A newly registered Application Load Balancer target (HTTP/HTTPS target group or Lambda target) becomes healthy after its first successful check. Network and Gateway target groups retain
HealthyThresholdCountfor initial admission. The threshold applies to every group when recovering fromunhealthy. - Health checks probe the target group's
HealthCheckPortwhen it is a port number, and each target's own port when it istraffic-port(the default). - Each
CreateListenerautomatically creates an immutable default rule (priority=default,isDefault=true). This rule cannot be deleted; useModifyListenerto change its action. - Rule priorities are unique per listener:
CreateRuleandSetRulePrioritiesonly reject a priority held by another rule on the same listener.SetRulePrioritiesis atomic: all priority assignments are validated before any change is committed. DeleteTargetGroupis rejected withResourceInUsewhile the target group is referenced by any listener or rule.- HTTPS and TLS certificate ARNs must refer to existing IAM server certificates or ACM certificates.
CreateListener,ModifyListenerandAddListenerCertificatesreject a blank or unknown ARN withCertificateNotFound. WhenModifyListenerchanges the protocol to HTTPS or TLS, it checks any inherited certificate ARNs too. An HTTPS listener also needs a default certificate:CreateListenerandModifyListenerreject an absent or empty effective certificate list withInvalidConfigurationRequest. A referenced IAM server certificate cannot be deleted:DeleteServerCertificatereturnsDeleteConflictuntil the certificate is removed from the listener. Writes recording a new IAM certificate reference hold IAM's certificate lock, so the certificate cannot be deleted between the check and the write. A refused change preserves the listener's previous port, protocol, policy and certificates. RemoveListenerCertificatesrefuses removal of an HTTPS or TLS listener's default certificate withOperationNotPermitted(400) and preserves the certificate list. UseModifyListenerto replace the default certificate. Additional certificates can still be removed.DeleteRuleis rejected withOperationNotPermittedfor the default rule.DescribeSSLPoliciesreturns a pre-seeded list of standard AWS SSL policies (ELBSecurityPolicy-*).DescribeAccountLimitsreturns standard default limits (e.g., 50 load balancers per region, 100 target groups, etc.).- Responses from HTTP targets preserve repeated header values, including multiple
Set-Cookieheaders. This also applies when a target rejects a WebSocket upgrade. - Duration-based ALB target stickiness is applied for instance and IP targets when
stickiness.enabled=trueandstickiness.type=lb_cookie(the default type). Requests without a usable cookie select a target normally; subsequent requests carrying the cookie return to that target while it remains eligible. Deregistered or unhealthy targets are replaced using the existing health-aware selection, including fail-open behavior when every target is unhealthy. - Sticky responses include opaque, authenticated
AWSALBandAWSALBCORScookies, without replacing application cookies.AWSALBCORStakes precedence and hasSameSite=None; Secure. Both cookies useExpiresseven days in the future; the configuredstickiness.lb_cookie.duration_seconds(default 86400, range 1 to 604800) separately limits the age of a target binding. Each response renews the binding. Restarting Floci invalidates existing bindings. Application-cookie stickiness, weighted target-group affinity, and NLB stickiness are not implemented. Cookie stickiness is not applied with target-group cross-zone balancing disabled orweighted_randomrouting. routing.http.preserve_host_header.enabled(defaultfalse) controls Host normalization for HTTP, WebSocket and Lambda targets. By default the client host is retained: listener ports 80 and 443 remove an incoming port; other listener ports are appended only when the client supplied none. An absolute HTTP(S) request target supplies the authority instead of the Host header. When enabled, the original Host headers are preserved, including repeated values. These are the ALB Host header rules; the backend address is never substituted for the client authority.routing.http.xff_header_processing.mode(defaultappend) controlsX-Forwarded-Forfor HTTP, WebSocket and Lambda targets.appendadds the client address to any value the client sent,preserveforwards the client's header unchanged, andremovedrops it.routing.http.xff_client_port.enabled(defaultfalse) adds the client port asip:portor[ipv6]:port, inappendmode only.ModifyLoadBalancerAttributesanswersInvalidConfigurationRequestfor any other value of either attribute.X-Forwarded-ProtoandX-Forwarded-Portare always set from the client's connection to the listener, replacing any value the client sent.RegisterTargetsrejects link-local and cloud instance-metadata addresses (169.254.0.0/16,fe80::/10,fd00:ec2::254) withInvalidTarget, and the load balancer and its health checks refuse to connect to them. Loopback and private addresses stay reachable so a load balancer can front a neighbouring container.- Requests forwarded to a target carry
X-Amzn-Trace-Id. A request without the header gets a newRootfield, a request with aRootfield gets a newSelffield, and an existingSelffield is updated. Other fields are kept. Above 7 KB of request headers the header is rewritten to a newRootfield. Floci does not send these traces to X-Ray.
Forwarding and network-security boundaries
An accepted NLB, listener, or target-group declaration confirms control-plane storage. It does not establish that the declared transport is implemented. ELBv2 supports local HTTP, HTTPS, and TCP listener sockets; other declared listener protocols and target types remain control-plane only.
| Declared listener protocol | Local forwarding behavior | Target types and transport |
|---|---|---|
HTTP |
Parses and forwards HTTP requests; supports WebSocket upgrades. | instance resolves an EC2 private address; ip uses the registered address. The target-group protocol selects HTTP or HTTPS to the backend. lambda invokes the registered function with an ALB event. |
HTTPS |
Terminates TLS with an ACM or IAM certificate, then handles HTTP as above. | Same targets and backend protocol selection as HTTP. |
TCP |
Relays bytes bidirectionally without HTTP parsing or TLS termination (enabling TLS pass-through to the target). Requires a dedicated local port. | instance resolves an EC2 private address; ip uses the registered address. Selected round-robin per connection. |
TLS |
Stored; certificate references are checked, but only HTTPS enables TLS on the local socket. TLS termination for NLB TLS listeners is unsupported (use a TCP listener for TLS pass-through). |
No NLB TLS backend transport is implemented. |
UDP, TCP_UDP |
Stored declarations do not create UDP sockets or UDP forwarding. | Datagram targets are unsupported. |
Gateway GENEVE |
Portless control-plane metadata only. | No GENEVE packet forwarding. |
alb target-type declarations do not implement NLB-to-ALB chaining. Use the HTTP, HTTPS,
or TCP rows for local routing. Do not use a successful registration alone as evidence of
TLS, UDP, or NLB target-type compatibility. Unsupported transports are not consistently
rejected by the management API: clients can instead see failed TLS handshakes or timeouts
on the listener socket.
Health checks
For non-Lambda targets, the checker sends an HTTP or HTTPS GET to HealthCheckPath
on HealthCheckPort, or the target's traffic port when configured as traffic-port.
HealthCheckProtocol selects TLS independently of the target's application protocol.
The response-code matcher and healthy/unhealthy thresholds affect target health.
HealthCheckProtocol=TCP does not perform a TCP-only probe.
Lambda targets are not actively probed. In ELBv2 mock mode, sockets
and active monitoring are disabled. The proxy can route to initial targets and fails
open to registered targets when none are healthy, so a successful request alone does
not prove that a health check passed.
Security groups and PrivateLink
Load-balancer security-group IDs are stored and returned by CreateLoadBalancer,
DescribeLoadBalancers, and SetSecurityGroups. The ELBv2 proxy and health checker do
not evaluate security-group ingress or egress rules, target security-group references,
network ACLs, or VPC/subnet routing. An internal scheme does not create a private
network boundary on the host. These declarations do not isolate reachable targets.
EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic is not handled by
SetSecurityGroups, is not returned as an enforcement setting, and does not filter
traffic. PrivateLink endpoint declarations do not add a separate ELBv2 ingress path
or apply the AWS client-IP-based filtering contract. On AWS, security groups filter
both client and target traffic, and the PrivateLink setting controls inbound-rule
application; see NLB security groups.
No allowed/denied traffic checks are claimed for these unimplemented controls. Use host firewalls, Docker network isolation, and published-port restrictions to control access to the emulator. Test AWS security-group and PrivateLink enforcement against AWS when that behavior is part of the application contract.
ARN Format
arn:aws:elasticloadbalancing:{region}:{account-id}:loadbalancer/app/{name}/{hex16}
arn:aws:elasticloadbalancing:{region}:{account-id}:targetgroup/{name}/{hex16}
arn:aws:elasticloadbalancing:{region}:{account-id}:listener/app/{lb-name}/{lb-id}/{hex16}
arn:aws:elasticloadbalancing:{region}:{account-id}:listener-rule/app/{lb-name}/{lb-id}/{listener-id}/{hex16}
Examples
export AWS_ENDPOINT_URL=http://localhost:4566
# Create a load balancer on two of the default VPC's subnets
aws elbv2 create-load-balancer \
--name my-alb \
--type application \
--scheme internet-facing \
--subnets subnet-default-us-east-1-a subnet-default-us-east-1-b
# Create a target group
aws elbv2 create-target-group \
--name my-targets \
--protocol HTTP \
--port 80 \
--target-type instance
# Register targets
aws elbv2 register-targets \
--target-group-arn arn:aws:elasticloadbalancing:us-east-1:000000000000:targetgroup/my-targets/abc123 \
--targets Id=i-00000000001,Port=8080
# Create a listener with a default forward action
aws elbv2 create-listener \
--load-balancer-arn arn:aws:elasticloadbalancing:us-east-1:000000000000:loadbalancer/app/my-alb/abc123 \
--protocol HTTP \
--port 80 \
--default-actions Type=forward,TargetGroupArn=arn:aws:elasticloadbalancing:us-east-1:000000000000:targetgroup/my-targets/abc123
# Add a path-based routing rule
aws elbv2 create-rule \
--listener-arn arn:aws:elasticloadbalancing:us-east-1:000000000000:listener/app/my-alb/abc123/def456 \
--priority 10 \
--conditions Field=path-pattern,Values='/api/*' \
--actions Type=forward,TargetGroupArn=arn:aws:elasticloadbalancing:us-east-1:000000000000:targetgroup/my-targets/abc123
# Describe load balancers
aws elbv2 describe-load-balancers
# Describe target health
aws elbv2 describe-target-health \
--target-group-arn arn:aws:elasticloadbalancing:us-east-1:000000000000:targetgroup/my-targets/abc123
# Tag a resource
aws elbv2 add-tags \
--resource-arns arn:aws:elasticloadbalancing:us-east-1:000000000000:loadbalancer/app/my-alb/abc123 \
--tags Key=env,Value=dev
# Clean up
aws elbv2 delete-listener \
--listener-arn arn:aws:elasticloadbalancing:us-east-1:000000000000:listener/app/my-alb/abc123/def456
aws elbv2 delete-load-balancer \
--load-balancer-arn arn:aws:elasticloadbalancing:us-east-1:000000000000:loadbalancer/app/my-alb/abc123
aws elbv2 delete-target-group \
--target-group-arn arn:aws:elasticloadbalancing:us-east-1:000000000000:targetgroup/my-targets/abc123
Configuration
| Environment variable | Default | Description |
|---|---|---|
FLOCI_SERVICES_ELBV2_ENABLED |
true |
Enable or disable the ELBv2 service |
FLOCI_SERVICES_ELBV2_BACKEND_KEEP_ALIVE |
true |
Reuse backend connections for ordinary HTTP forwarding. Set to false to open a fresh connection per request. |
FLOCI_SERVICES_ELBV2_BACKEND_KEEP_ALIVE_TIMEOUT_SECONDS |
60 |
Default timeout for unused backend HTTP/1.x connections in the pool, in seconds. Non-negative; 0 disables expiry. A target's Keep-Alive: timeout=... overrides this value. |
Backend connection reuse
Ordinary HTTP forwarding reuses backend HTTP/1.x connections by default. For local
targets that cannot reliably serve multiple requests on one connection, set
FLOCI_SERVICES_ELBV2_BACKEND_KEEP_ALIVE=false before starting Floci. This applies
to ordinary requests to HTTP and HTTPS targets, independently of client-to-listener
keep-alive. WebSocket upgrades keep their dedicated connection, and TCP forwarding
is unaffected.
To expire unused pooled connections sooner, set
FLOCI_SERVICES_ELBV2_BACKEND_KEEP_ALIVE_TIMEOUT_SECONDS below the target's idle
deadline. The default remains 60 seconds, matching the existing Vert.x client
default. This is the Vert.x HTTP/1.x keep-alive timeout,
not a request timeout or a maximum connection age: it does not interrupt an active
response. Vert.x honors a target's advertised Keep-Alive timeout in preference to
this default. Choose consistent target settings, or disable reuse if a fresh
connection is required for every request. The pool's periodic cleanup can delay
physical closure of an unused connection. This setting is unused when reuse is off
and is separate from the ALB idle_timeout.timeout_seconds attribute.
These are local transport controls, not AWS load-balancer attributes. Disabling reuse is a mitigation, not evidence of an AWS compatibility defect. A target that closes its connection while a request is outstanding can still produce a 502, as described in AWS's ALB troubleshooting guide. Floci does not retry forwarded requests when the target's outcome is uncertain, including a POST whose body the target consumed before closing.
Listener Ports
Listener sockets bind on the Floci host. Expose any listener ports you need in Docker Compose when Floci itself runs in a container, similar to RDS and ElastiCache proxy ports.
Two load balancers on the same port
In AWS each load balancer has its own DNS name and addresses, so two of them can both listen on
port 80 and never interact: the network picks the load balancer, and a host-header rule only picks
a rule inside one listener. Floci serves every load balancer from a single socket per port, so the
Host header has to carry both decisions. A template that puts a public and an internal load balancer
on port 80 is correct for AWS and stays accepted here, but the request has to name the one it wants.
A listener is chosen in this order:
- The Host header equals a load balancer's own DNS name (
{name}-{id}.elb.localhost.floci.io). - Exactly one listener on the port has a rule whose
host-headercondition matches the Host header. This uses the same matching as the rule evaluation that follows, so it is case-insensitive, ignores the port, and applies AWS's wildcards:*matches 0 or more characters and?matches exactly 1, which means*.example.comclaimstest.example.combut notexample.com.HostHeaderConfig.RegexValuesis not supported, by rule evaluation or by selection, so a load balancer that names itself only through a regex cannot be selected this way. - Only one listener is on the port, in which case it answers any Host header.
If none of those resolve, and in particular when two load balancers declare the same hostname or
neither declares any, the request answers 502 No listener for host. Floci logs a warning naming
both load balancers the first time a second one takes a port, because the targets behind them stay
healthy and nothing else reports the collision.
Giving each load balancer a host-header rule for the hostname it serves is usually enough, and it
is the same configuration AWS needs. Moving one load balancer to a different listener port also
works, at the cost of a Floci-only difference from the deployed template.