Jesse A. Green / notebook

OkHttp Admin & Architecture Guide

Generated June 2026 from square/okhttp at 7a35098

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

This guide is the deep reference for engineers, architects, and library maintainers integrating, operating, or extending OkHttp — the HTTP client for Java, Kotlin, and Android maintained by Square/Block. It documents OkHttp's architecture, its complete public configuration surface, the full module ecosystem, security posture, and internal design, all derived directly from the OkHttp 5.x source (commit 7a35098).

Where the User Guide shows how to make requests, this guide explains how OkHttp is built and how to operate it well in production.


1. Executive Summary

OkHttp is a mature, widely-deployed HTTP client distributed as a set of small, focused JVM/Android libraries under the Maven group com.squareup.okhttp3. It is the de-facto networking layer for a large share of the Android ecosystem and the transport beneath higher-level clients such as Retrofit.

Key characteristics:

  • Immutable, builder-based API. OkHttpClient, Request, Response, Headers, HttpUrl, and CacheControl are immutable value types created through Builder classes. Clients are cheaply derived with newBuilder().
  • Connection efficiency by default. A shared ConnectionPool reuses HTTP/1.x sockets and multiplexes HTTP/2. Transparent gzip, response caching, and Happy Eyeballs fast-fallback are built in.
  • Resilience. Automatic recovery from unreachable IPs, stale pooled connections, and unreachable proxies; automatic redirect, authentication-challenge, and retry handling.
  • Layered request processing. Every call flows through an ordered chain of interceptors (application then OkHttp's own then network), making behaviour observable and extensible.
  • Pluggable trust & DNS. TLS configuration, certificate pinning, custom trust managers, and DNS (including DNS-over-HTTPS) are all replaceable.
  • Standards-driven. Implements RFC 9110/9111/9112/9113 (HTTP semantics, caching, HTTP/1.1, HTTP/2), RFC 6455 (WebSockets), and SSE. Deliberately minimal in configurability where configuration would only serve to violate specs.

Runtime footprint: Android 5.0+ (API 21+) and Java 8+. Depends only on Okio and the Kotlin standard library. License: Apache 2.0.


2. Architecture

2.1 The request lifecycle

OkHttp models the work of satisfying one logical HTTP request — possibly involving redirects, authentication follow-ups, and retries across routes — as a single Call. A high-level request (Request) is rewritten, dispatched, connected, transmitted, and the response is read back, rewritten, and returned.

        ┌──────────────────────────────────────────────────────────────┐
        │                       OkHttpClient                            │
        │  (shared config: dispatcher, connection pool, interceptors,   │
        │   cache, dns, TLS, timeouts, protocols)                       │
        └───────────────┬───────────────────────────────────────────────┘
                        │ newCall(request)
                        ▼
                 ┌────────────┐   execute() / enqueue(Callback)
                 │    Call    │──────────────────────────────────┐
                 └────────────┘                                  │
                        │                                        ▼
                        │                                  ┌────────────┐
                        │            async path            │ Dispatcher │
                        │  ◀───────────────────────────────│ (limits +  │
                        │                                  │  executor) │
                        ▼                                  └────────────┘
        ┌──────────────────────────────────────────┐
        │            Interceptor Chain               │
        │  1. Application interceptors (your code)   │
        │  2. RetryAndFollowUpInterceptor            │
        │  3. BridgeInterceptor (cookies, gzip,      │
        │     Content-Length, User-Agent, Host…)     │
        │  4. CacheInterceptor (Cache read/write)    │
        │  5. ConnectInterceptor (pool → route →     │
        │     socket/TLS)                            │
        │  6. Network interceptors (your code)       │
        │  7. CallServerInterceptor (write request,  │
        │     read response)                         │
        └──────────────────┬─────────────────────────┘
                           ▼
        ┌──────────────────────────────────────────┐
        │  Connection  ←  Route  ←  Address  ← URL   │
        │  (ConnectionPool reuses & multiplexes)     │
        └──────────────────────────────────────────┘
                           ▼
                     Origin server

Note

The interceptor chain is the heart of OkHttp's design. Built-in behaviours (retries, header bridging, caching, connecting, transmitting) are themselves interceptors. Your application and network interceptors are inserted at the ends of this chain.

2.2 URL → Address → Route → Connection

OkHttp resolves what to connect to through four layered types (source: docs/features/connections.md):

Type Nature What it captures
HttpUrl Abstract scheme (http/https), host, port, path, query, fragment. Says what to fetch, not how.
Address Static The server plus all static connection config: port, HTTPS settings (TLS factory, hostname verifier, pinner), proxy authenticator, DNS, protocols, connection specs. URLs sharing an address can share a socket.
Route Dynamic A concrete IP (from DNS), a specific proxy (from ProxySelector), and the TLS version to negotiate. One address may yield many routes.
Connection Live An established socket (direct, TLS, or tunneled through an HTTP proxy) carrying requests. Pooled and reused.

When you request a URL, OkHttp: (1) builds an Address from the URL + client config; (2) tries to reuse a pooled Connection for that address; (3) if none, selects a Route (DNS lookup, proxy, TLS version); (4) connects (direct socket / TLS tunnel / direct TLS, with handshakes); (5) sends the request and reads the response; then returns the connection to the pool for reuse, evicting it after inactivity.

2.3 Request rewriting

OkHttp rewrites your high-level request before transmission for correctness and efficiency. It may add Content-Length, Transfer-Encoding, User-Agent, Host, Connection, Content-Type, Accept-Encoding: gzip (unless present), and a Cookie header (if a CookieJar has cookies). For stale cached responses it performs conditional GETs by adding If-Modified-Since / If-None-Match. On the response side, if transparent compression was used it drops Content-Encoding and Content-Length (they no longer describe the decompressed body), and merges network + cache responses for successful conditional GETs.

2.4 Dispatch model

  • Synchronous (Call.execute()): the caller's thread blocks; the caller manages concurrency.
  • Asynchronous (Call.enqueue(Callback)): the Dispatcher runs the call on its ExecutorService and invokes the callback on a dispatcher thread. The dispatcher enforces maxRequests (default 64) and maxRequestsPerHost (default 5).

2.5 Module topology

OkHttp is a multi-module Gradle/Kotlin-Multiplatform project. The core okhttp module targets commonJvmAndroid with jvmMain and androidMain source sets; feature modules layer onto it.

okhttp (core: okhttp3)
 ├── mockwebserver3              test server (+ junit4 / junit5 / deprecated mockwebserver)
 ├── logging-interceptor         okhttp3.logging
 ├── okhttp-tls                  okhttp3.tls (HeldCertificate, HandshakeCertificates)
 ├── okhttp-sse                  okhttp3.sse (EventSource)
 ├── okhttp-dnsoverhttps         okhttp3.dnsoverhttps (DnsOverHttps)
 ├── okhttp-brotli               okhttp3.brotli (BrotliInterceptor)
 ├── okhttp-zstd                 okhttp3.zstd (Zstd)
 ├── okhttp-coroutines           okhttp3.coroutines (executeAsync)
 ├── okhttp-urlconnection        JavaNetAuthenticator, JavaNetCookieJar
 ├── okhttp-java-net-cookiejar   okhttp3.java.net.cookiejar.JavaNetCookieJar
 ├── okhttp-idna-mapping-table   IDNA host-name mapping
 ├── okhttp-bom                  Bill of Materials (version alignment)
 └── okcurl                      CLI (okhttp3.curl)

Note

Each publishable module ships a checked-in api/*.api signature file (the Kotlin binary-compatibility validator output). These files are the authoritative, exhaustive list of every public class, field, and function — useful when auditing the API surface or planning an upgrade.

2.6 Repository structure

Path Contents
okhttp/ Core client. Public API in src/commonJvmAndroid/kotlin/okhttp3/; internals in okhttp3/internal/. Android specifics in src/androidMain/.
mockwebserver/, mockwebserver-junit4/, -junit5/, -deprecated/ Test server and integrations.
okhttp-* modules Optional features (see topology above).
okcurl/ Clikt-based CLI entry point.
samples/ Runnable examples: guide/recipes (30+ recipes), crawler, slack, static-server, unixdomainsockets, tlssurvey, compare.
docs/ MkDocs site: features/*.md (conceptual docs), changelogs/, security/, contribute/.
android-test/, regression-test/, container-tests/, okhttp-osgi-tests/, maven-tests/, native-image-tests/ Cross-environment test suites.
build-logic/ Gradle convention plugins (okhttp.jvm-conventions, etc.).

3. System Requirements

Concern Requirement
Java 8 or newer
Android 5.0+ (API level 21+)
Runtime dependencies Okio, Kotlin standard library (both small, backward-compatible)
Build (for contributors) Gradle with the configuration cache and isolated-projects enabled; multi-module KMP build
Optional TLS provider Conscrypt (BoringSSL-backed) — used automatically if installed as the first JCE security provider
License Apache License 2.0

Important

The legacy 3.12.x branch supports Android 2.3+ (API 9+) and Java 7+, but those platforms lack TLS 1.2 and must not be used for production. There is no security backport guarantee for that branch.

Optional Conscrypt activation:

Security.insertProviderAt(Conscrypt.newProvider(), 1);

4. Configuration Reference — OkHttpClient.Builder

OkHttpClient is configured exclusively through OkHttpClient.Builder. The table below lists every public builder setting with its default value, taken from the source.

4.1 Timeouts

Method Default Meaning
callTimeout(Long, TimeUnit) / (Duration) 0 (no timeout) Whole-call budget: DNS + connect + write + server + read, across all redirects/retries. For WebSockets/duplex, only the initial setup.
connectTimeout(Long, TimeUnit) / (Duration) 10_000 ms TCP connect to host.
readTimeout(Long, TimeUnit) / (Duration) 10_000 ms Socket reads and each response-body read.
writeTimeout(Long, TimeUnit) / (Duration) 10_000 ms Each request-body write.
pingInterval(Long, TimeUnit) / (Duration) 0 (disabled) HTTP/2 & WebSocket ping cadence; a missed pong fails the connection.
webSocketCloseTimeout(Long, TimeUnit) / (Duration) 60_000 ms Wait for graceful WebSocket shutdown after close().

All timeout values must be 0 (off) or between 1 and Integer.MAX_VALUE when converted to milliseconds. Each method has long+TimeUnit, java.time.Duration, and Kotlin Duration overloads.

4.2 Connections & protocols

Method Default Meaning
connectionPool(ConnectionPool) new pool Socket reuse pool. A default is created and shared if unset.
dispatcher(Dispatcher) new Dispatcher() Async concurrency policy + executor.
protocols(List<Protocol>) [HTTP_2, HTTP_1_1] Preferred protocols; ALPN-negotiated over HTTPS. Must contain HTTP_1_1 or be [H2_PRIOR_KNOWLEDGE]; never HTTP_1_0 or null. SPDY_3 is silently removed.
connectionSpecs(List<ConnectionSpec>) [MODERN_TLS, CLEARTEXT] TLS/cleartext negotiation policies, tried in order.
fastFallback(Boolean) true Happy Eyeballs (RFC 6555) concurrent connect racing. false reverts to 4.x sequential connects.
retryOnConnectionFailure(Boolean) true Silently recover from unreachable IPs, stale pooled connections, and unreachable proxies. Set false when retries would be destructive.
followRedirects(Boolean) true Follow HTTP redirects.
followSslRedirects(Boolean) true Follow cross-scheme redirects (HTTP↔HTTPS); still gated by followRedirects.
dns(Dns) Dns.SYSTEM Hostname → IP resolver.
socketFactory(SocketFactory) system default Creates unconnected sockets (must not be an SSLSocketFactory).
proxy(Proxy) none Explicit proxy; takes precedence over proxySelector. Use Proxy.NO_PROXY to disable proxying entirely.
proxySelector(ProxySelector) system default Proxy selection when no explicit proxy is set.

4.3 TLS & trust

Method Default Meaning
sslSocketFactory(SSLSocketFactory, X509TrustManager) platform default Secure HTTPS connections. Preferred overload.
sslSocketFactory(SSLSocketFactory) — Deprecated (DeprecationLevel.ERROR): forces reflection to recover the trust manager.
hostnameVerifier(HostnameVerifier) OkHostnameVerifier Confirms a server certificate matches the requested hostname.
certificatePinner(CertificatePinner) CertificatePinner.DEFAULT (no pins) Restricts trusted certificates per host.

Caution

If no connection spec is TLS-capable (CLEARTEXT-only client), the client has no SSL socket factory and accessing sslSocketFactory throws IllegalStateException("CLEARTEXT-only client"). The builder validates this invariant at build() time.

4.4 Behaviour & integrations

Method Default Meaning
addInterceptor(Interceptor) — Append an application interceptor (sees the original request, runs once).
addNetworkInterceptor(Interceptor) — Append a network interceptor (sees redirects/retries and the live Connection).
authenticator(Authenticator) Authenticator.NONE Responds to origin (401) challenges.
proxyAuthenticator(Authenticator) Authenticator.NONE Responds to proxy (407) challenges.
cookieJar(CookieJar) CookieJar.NO_COOKIES Stores/sends cookies.
cache(Cache) none Response cache (see §6).
eventListener(EventListener) EventListener.NONE Single shared metrics listener.
eventListenerFactory(EventListener.Factory) — Per-call metrics listener factory.
minWebSocketMessageToCompress(Long) 1024 Minimum outbound WS message size (bytes) eligible for compression; 0 compresses all.

Tip

Mutating a route-affecting setting (dns, proxy, proxySelector, proxyAuthenticator, socketFactory, sslSocketFactory, connectionSpecs, protocols, hostnameVerifier, certificatePinner) on a derived builder resets the internal RouteDatabase so stale route blacklists don't leak between configurations.


5. Public API Reference

The core okhttp3 package (artifact okhttp, signatures from okhttp/api/jvm/okhttp.api) exposes the following public types. Builder/value types are immutable; interfaces are extension points.

5.1 Core request/response types

Type Kind Purpose
OkHttpClient class (Call.Factory, WebSocket.Factory) The configured client. newCall(), newWebSocket(), newBuilder(), plus read-only accessors for every setting.
Request immutable One HTTP request: url(), method(), headers(), body(), cacheControl(), tag(), toCurl(), newBuilder().
Request.Builder builder url(...), get/head/post/put/patch/delete/method(...), header/addHeader/removeHeader, headers, cacheControl, tag, gzip(), cacheUrlOverride.
Response immutable (Closeable) code(), message(), isSuccessful(), isRedirect(), headers(), body(), peekBody(n), request(), protocol(), handshake(), cacheResponse(), networkResponse(), priorResponse(), challenges(), trailers(), sentRequestAtMillis(), receivedResponseAtMillis().
Response.Builder builder Construct synthetic responses (used by interceptors and tests).
RequestBody abstract contentType(), contentLength(), writeTo(sink), isOneShot(), isDuplex(), sha256(), plus many create(...) factories (String, byte[], File, FileDescriptor, ByteString, Okio Path).
ResponseBody abstract (Closeable) contentType(), contentLength(), string(), bytes(), byteString(), source(), byteStream(), charStream().
Call interface (Cloneable) execute(), enqueue(callback), cancel(), isExecuted(), isCanceled(), request(), timeout(), clone(), addEventListener(), tag(...).
Call.Factory interface newCall(request).
Callback interface onResponse(call, response), onFailure(call, e).

5.2 Headers, URLs, media types, bodies

Type Purpose
Headers / Headers.Builder Multi-map of header name/value pairs; get, values, name(i), value(i), getDate, getInstant, toMultimap, of(...). Builder adds add, addUnsafeNonAscii, set, removeAll.
HttpUrl / HttpUrl.Builder Typed URL with full encode/decode accessors, resolve(), redact(), topPrivateDomain(), queryParameter*, defaultPort(), conversions to/from java.net.URI/URL.
MediaType Parsed Content-Type: type(), subtype(), charset(), parameter(); MediaType.get(str) / parse(str).
FormBody / FormBody.Builder application/x-www-form-urlencoded body.
MultipartBody / .Builder / .Part multipart/* body with predefined types MIXED, ALTERNATIVE, DIGEST, PARALLEL, FORM.
MultipartReader / .Part Parse multipart responses.
CacheControl / .Builder Cache-Control directive model; constants FORCE_CACHE, FORCE_NETWORK.

5.3 Connection, TLS & negotiation types

Type Purpose
Connection Live connection: route(), socket(), handshake(), protocol().
ConnectionPool Socket reuse pool: connectionCount(), idleConnectionCount(), evictAll().
ConnectionSpec / .Builder TLS policy; constants RESTRICTED_TLS, MODERN_TLS, COMPATIBLE_TLS, CLEARTEXT.
CipherSuite ~150 named TLS cipher-suite constants; forJavaName(), javaName().
TlsVersion enum SSL_3_0, TLS_1_0, TLS_1_1, TLS_1_2, TLS_1_3.
Protocol enum HTTP_1_0, HTTP_1_1, HTTP_2, H2_PRIOR_KNOWLEDGE, HTTP_3, QUIC, SPDY_3 (deprecated).
Handshake TLS handshake details: tlsVersion(), cipherSuite(), peerCertificates(), localCertificates(), principals.
CertificatePinner / .Builder / .Pin Certificate pinning; static pin(), sha256Hash(), sha1Hash().
Address Static connection configuration for a server.
Route A concrete IP + proxy + spec attempt; requiresTunnel().
Dns interface; lookup(host); constant Dns.SYSTEM.
Dispatcher Async concurrency: maxRequests, maxRequestsPerHost, queuedCalls, runningCalls, cancelAll, executorService.

5.4 Extension-point interfaces & callbacks

Type Purpose
Interceptor / Interceptor.Chain Observe/rewrite/retry calls. The chain exposes request(), proceed(), connection(), call(), the resolved timeouts, and with* methods to derive a chain with overridden config/timeouts. Interceptor.invoke { } (Kotlin) builds one from a lambda.
Authenticator Respond to challenges; constants NONE, JAVA_NET_AUTHENTICATOR.
CookieJar Cookie storage; constant NO_COOKIES.
EventListener / .Factory ~30 lifecycle callbacks (DNS, connect, secure-connect, request/response headers & body, cache hit/miss, retry/follow-up decisions, etc.); NONE; plus() to combine.
WebSocket / WebSocket.Factory / WebSocketListener WebSocket send/close/cancel and onOpen/onMessage/onClosing/onClosed/onFailure.
Credentials basic(user, pass[, charset]) helper.
Challenge A parsed WWW-Authenticate/Proxy-Authenticate challenge: scheme(), realm(), authParams(), charset().
Cookie / .Builder RFC 6265 cookie model; parse(), parseAll(), matches().
CompressionInterceptor / .DecompressionAlgorithm Pluggable response decompression; Gzip is built in.
TrailersSource Source of HTTP trailers; constant EMPTY.
OkHttp OkHttp.VERSION constant; OkHttp.initialize(context) on Android.

5.5 Feature-module APIs

Module Public API
logging-interceptor HttpLoggingInterceptor (Level = NONE/BASIC/HEADERS/BODY; redactHeader, redactQueryParams; pluggable Logger), LoggingEventListener (+ .Factory).
okhttp-tls HeldCertificate (+ .Builder: commonName, addSubjectAlternativeName, validityInterval, serialNumber, certificateAuthority, signedBy, rsa2048/ecdsa256), HandshakeCertificates (+ .Builder: addTrustedCertificate, addPlatformTrustedCertificates, addInsecureHost, heldCertificate), Certificates (PEM encode/decode).
okhttp-sse EventSource, EventSource.Factory, EventSourceListener (onOpen/onEvent/onClosed/onFailure), EventSources.createFactory(...) / processResponse(...).
okhttp-dnsoverhttps DnsOverHttps (+ .Builder: client, url, includeIPv6, post, resolvePrivate/PublicAddresses, bootstrapDnsHosts, systemDns).
okhttp-brotli BrotliInterceptor.INSTANCE, Brotli algorithm.
okhttp-zstd Zstd decompression algorithm.
okhttp-coroutines Call.executeAsync() suspend extension.
okhttp-urlconnection JavaNetAuthenticator, JavaNetCookieJar.
okhttp-java-net-cookiejar okhttp3.java.net.cookiejar.JavaNetCookieJar(CookieHandler).
mockwebserver3 MockWebServer, MockResponse (+ .Builder), RecordedRequest, Dispatcher, QueueDispatcher, SocketEffect, PushPromise.

6. Caching Internals

The optional Cache is a disk-backed, RFC-9111-aligned response store with browser-like heuristics. It is implemented as the CacheInterceptor within the chain.

Construction: Cache(File directory, long maxSize) or Cache(FileSystem, Path, long maxSize) (Okio file system). One directory per Cache; the directory is exclusively owned.

Behaviour:

  • Default freshness for documents without explicit expiry is 10% of the document's age at serve time (based on Last-Modified); not applied to URLs containing a query.
  • Three outcomes, observable via EventListener: Cache Hit (no network), Cache Miss (network used; uncacheable/expired/never-fetched), Conditional Hit (cacheConditionalHit then a revalidation request; the cached body is reused only on 304 Not Modified, so both cacheResponse() and networkResponse() are non-null).
  • A response is stored only if its body is fully read, canceled, or stalled.

Operations & stats: evictAll(), delete(), urls() iterator (with remove()), flush(), close(), size(), maxSize(), and counters hitCount(), networkCount(), requestCount(), writeSuccessCount(), writeAbortCount().

Warning

Sharing a cache directory between two Cache instances or processes corrupts it. In multi-process apps, give each process its own directory or a single shared client.


7. Security Analysis

OkHttp's threat model centers on protecting transport confidentiality/integrity while maximizing connectivity. Security-relevant subsystems and operational guidance follow.

7.1 TLS posture

  • Defaults to MODERN_TLS + CLEARTEXT; uses the platform TLS stack (or Conscrypt if installed first). TLS versions/cipher suites in each ConnectionSpec evolve per release — historically OkHttp dropped SSL 3.0 (POODLE) and RC4 as attacks emerged.
  • RESTRICTED_TLS is available for stricter compliance environments.
  • Hostname verification (OkHostnameVerifier) always runs in addition to certificate trust, even with custom Android trust managers.

Important

Staying current with OkHttp is itself a security control: the library tracks the TLS ecosystem and removes weak primitives. Pin your dependency to a recent 5.x release and update regularly.

7.2 Certificate pinning

CertificatePinner lets you constrain trust to specific public-key hashes, mitigating CA compromise (e.g. the 2011 DigiNotar attack). Pinning is double-edged: an uncoordinated server certificate rotation will hard-fail every pinned client.

Caution

Never deploy certificate pins without your server TLS team's sign-off and a rotation plan. Prefer pinning an intermediate/CA key over a leaf certificate to reduce rotation breakage, and ship backup pins.

7.3 Authentication & credential handling

  • Authenticator callbacks must guard against retry loops by returning null when an Authorization header is already present (see community issue #9477, "Infinite Authentication Loop in Proxy CONNECT Tunnel").
  • Credentials.basic Base64-encodes credentials — Basic auth offers no confidentiality without TLS.
  • HttpUrl.redact() produces a credential-stripped URL safe for logs.

7.4 Logging hygiene

HttpLoggingInterceptor at HEADERS/BODY level will log sensitive headers and payloads. Use redactHeader("Authorization"), redactHeader("Cookie"), and redactQueryParams(...), and never enable BODY logging for authenticated traffic in production.

7.5 Known security-relevant issues (community-reported)

These open/closed issues from the project tracker inform hardening decisions; consult the upstream issue and your installed version before relying on a given behaviour:

Issue Topic Operational note
#9476 SSRF via unrestricted redirect following If you fetch untrusted/user-supplied URLs, consider followRedirects(false) and validate redirect targets in an interceptor.
#9477 Infinite auth loop in proxy CONNECT tunnel Guard Authenticator against re-attempting with an existing Authorization.
#9434 InsecureAndroidTrustManager MITM concern Never use insecure/all-trusting trust managers outside tests.
#9472 (closed) Predictable WebSocket masking keys Fixed; keep current.
#9473 (closed) Gzip decompression bomb Bound response sizes for untrusted servers; don't blindly string() arbitrary bodies.
#9474 (closed) CRLF header injection via addUnsafeNonAscii() Avoid addUnsafeNonAscii with untrusted header values.
#9451 HttpUrl.isDotDot path-traversal forms Relevant if you use OkHttp URL parsing for sandboxing path checks.
#9335 Cache entries not stored correctly on Windows On Windows, validate cache hit rates; excessive requests may indicate this bug.

Caution

When fetching attacker-controllable URLs (webhooks, link unfurling, image proxies), treat redirect following and decompression as attack surface: disable or constrain redirects, cap body sizes, and resolve/deny internal IP ranges via a custom Dns or network interceptor to prevent SSRF.


8. Operations

8.1 Lifecycle management

OkHttp requires no explicit shutdown — idle dispatcher threads and pooled connections self-release; HTTP/2 daemon threads exit when idle. For aggressive resource reclamation (CLI tools, short-lived workers):

client.dispatcher().executorService().shutdown(); // rejects future calls
client.connectionPool().evictAll();
if (client.cache() != null) client.cache().close();

Warning

After executorService().shutdown() the client rejects new calls. After cache().close(), issuing a call against that cache crashes — close the cache only during teardown.

8.2 Tuning for throughput

  • Raise Dispatcher.maxRequests / maxRequestsPerHost for high-concurrency async workloads, and back the dispatcher with an executor sized to match.
  • Keep one shared OkHttpClient (and thus one ConnectionPool) per process so connections are actually reused.
  • Prefer HTTP/2 (the default) for many concurrent requests to one host — they multiplex over a single socket.
  • Use pingInterval on long-lived connections to detect dead peers promptly.

Note

Issue #9443 notes that the dispatcher executor must actually be able to run maxRequests concurrently — a too-small thread pool silently caps real concurrency below the configured maximum.

8.3 Observability

  • Metrics: an EventListener.Factory gives per-call timing for every network phase; sample (e.g. 10%) to bound overhead. Cache hit/miss/conditional events flow through the same listener.
  • Logging: LoggingEventListener.Factory for phase timings, or HttpLoggingInterceptor for wire-level request/response logs (redact secrets).
  • Pool inspection: connectionPool().connectionCount() / idleConnectionCount() and dispatcher().runningCallsCount() / queuedCallsCount() expose live load.

8.4 Proxy & DNS operations

  • Route all traffic through a fixed proxy with proxy(...), or delegate to proxySelector(...). proxyAuthenticator(...) handles proxy 407 challenges.
  • Replace name resolution wholesale with a custom Dns, or use DnsOverHttps for encrypted resolution (configure a bootstrap client and DoH endpoint).

9. Code Quality, Patterns & Conventions

  • Kotlin-first, Java-friendly. Core is Kotlin with @JvmName/@JvmStatic/@JvmOverloads and Companion-object factories so Java callers get idiomatic APIs (Headers.of(...), MediaType.get(...)).
  • Immutability + builders. Value types are immutable; the only mutation path is a Builder. newBuilder() enables cheap, copy-on-write derivation that shares pools.
  • Deprecation discipline. Property-style getters that replaced old method-style accessors are retained as @Deprecated(level = ERROR) -deprecated_* shims (visible throughout the .api files) to preserve binary compatibility while steering callers to val accessors.
  • Binary-compatibility validation. Checked-in api/*.api signature files are enforced in CI, preventing accidental public-API breakage.
  • Internal encapsulation. Everything under okhttp3.internal is non-public by convention (the open issue #9435 tracks formalizing this as internal or promoting parts to API). Do not depend on internal classes.
  • KMP source sets. commonJvmAndroid holds shared JVM/Android code; androidMain and jvmMain carry platform specifics, allowing one codebase to target both.
  • Multiplatform value semantics. Inline-class-backed durations appear in the .api as mangled names (e.g. callTimeout-LRDsOJo) — these are Kotlin Duration overloads, not separate Java API.

10. Testing Strategy

OkHttp dogfoods its own MockWebServer and maintains an unusually broad test matrix:

Suite Validates
mockwebserver3 + unit tests Protocol behaviour against a real scriptable server (delays, throttling, chunking, HTTP/2 push, TLS handshake failures, 100-Continue, WebSockets).
android-test, android-test-app, regression-test On-device/emulator instrumentation (e.g. ALPN, SNI, Let's Encrypt trust).
container-tests Behaviour inside containers.
okhttp-osgi-tests OSGi bundle compatibility.
maven-tests Consuming OkHttp via Maven + the BOM version range.
native-image-tests GraalVM native-image compatibility (reachability metadata under META-INF/native-image).
okhttp-hpacktests HTTP/2 HPACK header-compression conformance (shared test cases).
samples/tlssurvey, samples/compare TLS ecosystem surveys and cross-client comparison.
fuzzing Fuzz harnesses for parsers.

Tip

For consumers, MockWebServer is the recommended test tool: it exercises the genuine network stack rather than mocking the client. Pair with okhttp-tls HeldCertificate to test HTTPS paths without external CAs.


11. Integration Patterns

  • Retrofit / higher-level clients. OkHttp is the standard transport under Retrofit; share one OkHttpClient and add cross-cutting concerns (auth, logging, metrics) as interceptors.
  • java.net interop. okhttp-urlconnection and okhttp-java-net-cookiejar bridge java.net.Authenticator and java.net.CookieHandler/CookieManager into OkHttp.
  • JSON. Stream ResponseBody.source() into Moshi/Gson/kotlinx.serialization rather than buffering with string().
  • Coroutines. okhttp-coroutines executeAsync() integrates cleanly with structured concurrency and cancellation.
  • R8/ProGuard. See docs/features/r8_proguard.md; OkHttp ships consumer rules, but verify keep rules for reflective TLS/platform code on Android release builds.

12. Quick Reference

Maven coordinates: com.squareup.okhttp3:okhttp:5.x (core) · :okhttp-bom:5.x (version alignment).

Defaults at a glance:

Setting Default
connect / read / write timeout 10 s each
call timeout none (0)
ping interval disabled (0)
WebSocket close timeout 60 s
protocols HTTP/2, then HTTP/1.1
connection specs MODERN_TLS, CLEARTEXT
fast fallback (Happy Eyeballs) enabled
retry on connection failure enabled
follow redirects / SSL redirects enabled
dispatcher maxRequests / perHost 64 / 5
cookie jar none
cache none
authenticator / proxy authenticator none
min WebSocket message to compress 1024 bytes

Minimal client + request:

OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url("https://example.com").build();
try (Response response = client.newCall(request).execute()) {
  System.out.println(response.code());
  System.out.println(response.body().string());
}

Production-leaning client:

OkHttpClient client = new OkHttpClient.Builder()
    .connectTimeout(Duration.ofSeconds(10))
    .callTimeout(Duration.ofSeconds(30))
    .pingInterval(Duration.ofSeconds(30))
    .cache(new Cache(cacheDir, 50L * 1024 * 1024))
    .addInterceptor(authInterceptor)
    .eventListenerFactory(metricsFactory)
    .build();

Operational commands:

client.connectionPool().evictAll();                 // drop pooled sockets
client.dispatcher().cancelAll();                     // cancel all async calls
client.dispatcher().executorService().shutdown();    // stop accepting calls
client.cache().close();                              // close the cache (teardown only)