Choosing the Right Tomcat Connector: HTTP/1.1, HTTP/2, or AJP
A decision guide for selecting Tomcat connector protocols (HTTP/1.1, HTTP/2, AJP) based on deployment topology, performance needs, and reverse-proxy architecture. Covers Tomcat 9.0.x and 10.1.x LTS with concrete configurations and validation steps.
20 Jan 2026, 05:48 UTC

The Decision You're Facing
Every Tomcat deployment needs at least one connector, but the protocol choice shapes latency, security posture, and operational complexity. If you're terminating TLS at Tomcat, running behind a reverse proxy, or serving clients that may not support HTTP/2, the default HTTP/1.1 connector isn't always the right answer. This guide walks through the supported options in Tomcat 9.0.x and 10.1.x LTS branches, matches them to common topologies, and shows how to validate the configuration.
Quick Comparison
| Protocol | Connector Class | Typical Port | TLS Required | Best Fit | Key Constraint |
|---|---|---|---|---|---|
| HTTP/1.1 | org.apache.coyote.http11.Http11NioProtocol | 8080 / 8443 | Optional | Direct client access, TLS termination at Tomcat, legacy client support | No multiplexing; head-of-line blocking on multi-resource pages |
| HTTP/2 (h2) | org.apache.coyote.http11.Http2Protocol | 8443 | Yes (ALPN) | Modern browsers, TLS-terminating Tomcat, latency-sensitive apps | Requires Java 8+ with ALPN; cipher suite restrictions apply |
| HTTP/2 Cleartext (h2c) | org.apache.coyote.http11.Http2Protocol | 8080 | No | Internal meshes, trusted networks, upgrade via HTTP/1.1 | Most browsers refuse h2c; upgrade handshake adds latency |
| AJP/1.3 | org.apache.coyote.ajp.AjpNioProtocol | 8009 | No (typically) | Apache httpd or Nginx reverse proxy in front of Tomcat | No HTTP/2 support; must bind to localhost or trusted VLAN; secret required |
When to Choose Each Protocol
HTTP/1.1: The Safe Default
Use HTTP/1.1 when you terminate TLS at Tomcat and serve a mixed client base, or when you need the simplest debugging experience. The Http11NioProtocol uses non-blocking I/O and scales well with keep-alive tuned. It's also the only option if you're running on a JVM without ALPN support (pre-Java 8) or in environments where cipher suite control is limited.
HTTP/2: Multiplexing for Latency-Critical Paths
HTTP/2 shines when a single page loads dozens of resources (CSS, JS, images) over the same connection. Multiplexing eliminates head-of-line blocking, and HPACK header compression reduces overhead. In Tomcat, you enable it by nesting an <UpgradeProtocol> element inside an HTTP/1.1 connector that has SSLEnabled="true", or by defining a dedicated HTTP/2 connector on a separate port. Both approaches require TLS with ALPN negotiation—browsers will not speak h2 without it.
AJP: Reverse-Proxy Integration
AJP exists to pass request metadata (headers, SSL client certs, remote IP) efficiently from a front-end web server to Tomcat. It adds roughly 1–2 ms per request versus direct HTTP but lets Apache httpd or Nginx handle static files, TLS termination, and load balancing. Since the Ghostcat vulnerability (CVE-2020-1938), Tomcat 9.0.31+ and 10.0.0+ default secretRequired="true"; you must generate a shared secret and configure it in both server.xml and the proxy module.
Concrete Configuration Patterns
Single Port: HTTP/1.1 with HTTP/2 Upgrade (Recommended for Most TLS Terminations)
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
SSLEnabled="true" scheme="https" secure="true"
maxThreads="200" acceptCount="100"
keystoreFile="${catalina.base}/conf/keystore.p12"
keystoreType="PKCS12" keystorePass="changeit"
ciphers="TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256,TLS_AES_128_GCM_SHA256,ECDHE_RSA_WITH_AES_256_GCM_SHA384,ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,ECDHE_RSA_WITH_AES_128_GCM_SHA256"
>
<UpgradeProtocol className="org.apache.coyote.http11.Http2Protocol" />
</Connector>
This single connector listens on 8443, negotiates HTTP/2 via ALPN for capable clients, and falls back to HTTP/1.1 for others. The cipher list prioritizes HTTP/2-compatible suites (ECDHE + AES-GCM or ChaCha20-Poly1305). Run this on the Tomcat host with write access to $CATALINA_BASE/conf/server.xml and the keystore file. Restart Tomcat after changes.
Separate Ports: Dedicated HTTP/2 Cleartext (h2c) for Internal Mesh
<!-- HTTP/1.1 on 8080 -->
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="200" acceptCount="100" />
<!-- HTTP/2 cleartext on 8081 -->
<Connector port="8081" protocol="org.apache.coyote.http11.Http2Protocol"
SSLEnabled="false" scheme="http" secure="false"
maxThreads="200" acceptCount="100" />
Use this only in trusted networks (service mesh, sidecar proxies). Browsers will not use h2c; they require the upgrade handshake from HTTP/1.1.
AJP with Required Secret (Tomcat 9.0.31+ / 10.0.0+)
<Connector port="8009" protocol="org.apache.coyote.ajp.AjpNioProtocol"
address="127.0.0.1"
secretRequired="true"
requiredSecret="BASE64_GENERATED_SECRET"
maxThreads="200" acceptCount="100" />
Generate the secret once: openssl rand -base64 32. Paste the output into requiredSecret above and into your proxy config (e.g., Apache ProxyPass ajp://localhost:8009/ secret=BASE64_GENERATED_SECRET or Nginx ajp_pass with ajp_secret). Bind to 127.0.0.1 or a specific VLAN interface—never 0.0.0.0. If you must expose AJP beyond localhost, add a RemoteAddrValve to the <Engine> or <Host> to restrict by IP.
Validation Checklist
- Startup logs: Confirm the protocol handler names. Look for
Starting ProtocolHandler ["http-nio-8443"]or["ajp-nio-8009"]incatalina.out. - HTTP/2 negotiation: From a client machine with curl 7.47+:
Verify the response showscurl -v --http2 https://localhost:8443/HTTP/2 200andalt-svc: h2=":8443"headers. If you seeHTTP/1.1 200, ALPN failed—check cipher suites and Java version. - AJP secret handshake: Enable DEBUG for
org.apache.coyote.ajpinlogging.properties, restart, and make a proxied request. You should seeSecret validatedin the logs. A 503 with "Secret required" means the proxy isn't sending the secret or it mismatches. - Thread pool health: Open JConsole, connect to the Tomcat JVM, and navigate to
Catalina:type=ThreadPool,name=*. WatchcurrentThreadCountvsmaxThreadsunder load. HTTP/2 multiplexing reduces connection count but increases per-connection memory; you may need to lowermaxThreadscompared to HTTP/1.1. - Cipher suite verification: On the Tomcat host:
Ensure at least one ECDHE+AES-GCM or ChaCha20-Poly1305 suite is offered. Missing these will cause browsers to fall back to HTTP/1.1.nmap --script ssl-enum-ciphers -p 8443 localhost
Performance Trade-offs in Practice
Benchmarks vary by workload, but the general pattern holds: HTTP/2 reduces total page-load time for multi-resource pages by 15–40% over HTTP/1.1 when RTT is above 20 ms. AJP adds a small fixed overhead (1–2 ms) per request but offloads static serving and TLS to the web server, which often nets a win for mixed workloads. HTTP/1.1 with tuned keep-alive (keepAliveTimeout=30000, maxKeepAliveRequests=100) remains the lowest CPU-per-connection option for simple APIs or health-check endpoints.
Security Posture Summary
- HTTP/1.1 + TLS: Encryption terminates at Tomcat. Manage certificates and cipher suites in
server.xml. - HTTP/2: Same TLS termination, but stricter cipher requirements. Avoid RSA key exchange; prefer ECDHE.
- AJP: Typically runs unencrypted on localhost or trusted VLAN. The
requiredSecretmitigates unauthorized access, but defense-in-depth demands network-level isolation (firewall, security groups,RemoteAddrValve).
Limitations and Gotchas
- HTTP/2 Server Push (
PushBuilderAPI) is deprecated in Servlet 6.0 (Tomcat 10.1). UseLink: </style.css>; rel=preload; as=styleheaders or Early Hints (103) instead. - Tomcat 9.0.x reaches end of life in 2026; plan migration to 10.1.x LTS. Connector class names remain the same, but the servlet API namespace changes from
javax.*tojakarta.*. - If you run behind a load balancer that terminates TLS, configure
RemoteIpValvewithinternalProxiesandprotocolHeader="X-Forwarded-Proto"so Tomcat generates correct redirect URLs and logs the original scheme. - Java 8's built-in ALPN support is limited; Tomcat bundles OpenJSSE as a fallback. Verify ALPN is active by checking startup logs for "ALPN callback" messages.
Rollback Consideration
Changing connectors modifies server.xml and requires a Tomcat restart. If a new connector fails to start (port conflict, keystore error, secret mismatch), Tomcat will log the failure and continue with other connectors. To roll back, revert server.xml and restart. No data migration or state change occurs beyond the configuration file.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.