diff --git a/build.gradle b/build.gradle
index 1858ab829..377834aa1 100644
--- a/build.gradle
+++ b/build.gradle
@@ -24,7 +24,7 @@ buildscript {
         classpath 'com.palantir.gradle.externalpublish:gradle-external-publish-plugin:1.4.0'
         classpath 'com.palantir.gradle.revapi:gradle-revapi:1.5.0'
         classpath 'com.palantir.javaformat:gradle-palantir-java-format:2.2.0'
-        classpath 'com.palantir.baseline:gradle-baseline-java:4.25.0'
+        classpath 'com.palantir.baseline:gradle-baseline-java:4.28.0'
         classpath 'com.palantir.gradle.gitversion:gradle-git-version:0.12.3'
         classpath 'gradle.plugin.org.inferred:gradle-processors:3.6.0'
         classpath 'com.palantir.metricschema:gradle-metric-schema:0.8.0'
diff --git a/dialogue-httpurlconnection-client/build.gradle b/dialogue-httpurlconnection-client/build.gradle
deleted file mode 100644
index 02b63d961..000000000
--- a/dialogue-httpurlconnection-client/build.gradle
+++ /dev/null
@@ -1,13 +0,0 @@
-dependencies {
-    api project(':dialogue-core')
-    api project(':dialogue-target')
-    api 'com.palantir.conjure.java.runtime:client-config'
-    implementation project(':dialogue-blocking-channels')
-    implementation 'com.palantir.safe-logging:preconditions'
-
-    testImplementation project(':dialogue-test-common')
-    testImplementation project(':dialogue-serde')
-    implementation 'com.palantir.safe-logging:logger'
-}
-
-tasks.checkImplicitDependenciesMain.enabled = false // not published, don't care
diff --git a/dialogue-httpurlconnection-client/src/main/java/com/palantir/dialogue/httpurlconnection/HttpUrlConnectionBlockingChannel.java b/dialogue-httpurlconnection-client/src/main/java/com/palantir/dialogue/httpurlconnection/HttpUrlConnectionBlockingChannel.java
deleted file mode 100644
index bd61869f1..000000000
--- a/dialogue-httpurlconnection-client/src/main/java/com/palantir/dialogue/httpurlconnection/HttpUrlConnectionBlockingChannel.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * (c) Copyright 2020 Palantir Technologies Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.palantir.dialogue.httpurlconnection;
-
-import com.google.common.collect.Iterables;
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.MultimapBuilder;
-import com.google.common.primitives.Ints;
-import com.palantir.conjure.java.client.config.ClientConfiguration;
-import com.palantir.dialogue.Endpoint;
-import com.palantir.dialogue.HttpMethod;
-import com.palantir.dialogue.Request;
-import com.palantir.dialogue.RequestBody;
-import com.palantir.dialogue.Response;
-import com.palantir.dialogue.ResponseAttachments;
-import com.palantir.dialogue.blocking.BlockingChannel;
-import com.palantir.dialogue.core.BaseUrl;
-import com.palantir.logsafe.Preconditions;
-import com.palantir.logsafe.exceptions.SafeRuntimeException;
-import com.palantir.logsafe.logger.SafeLogger;
-import com.palantir.logsafe.logger.SafeLoggerFactory;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.util.Objects;
-import java.util.Optional;
-import javax.net.ssl.HttpsURLConnection;
-
-final class HttpUrlConnectionBlockingChannel implements BlockingChannel {
-    private static final SafeLogger log = SafeLoggerFactory.get(HttpUrlConnectionBlockingChannel.class);
-
-    private final ClientConfiguration config;
-    private final BaseUrl baseUrl;
-
-    HttpUrlConnectionBlockingChannel(ClientConfiguration config, URL baseUrl) {
-        this.config = config;
-        this.baseUrl = BaseUrl.of(baseUrl);
-    }
-
-    @Override
-    public Response execute(Endpoint endpoint, Request request) throws IOException {
-        // Create base request given the URL
-        HttpURLConnection connection =
-                (HttpURLConnection) baseUrl.render(endpoint, request).openConnection();
-        connection.setRequestMethod(endpoint.httpMethod().name());
-
-        // Fill headers
-        request.headerParams().forEach(connection::addRequestProperty);
-
-        connection.setConnectTimeout(Ints.checkedCast(config.connectTimeout().toMillis()));
-        connection.setReadTimeout(Ints.checkedCast(config.readTimeout().toMillis()));
-
-        // match okhttp behavior
-        connection.setInstanceFollowRedirects(false);
-
-        // Never ask users for credentials
-        connection.setAllowUserInteraction(false);
-        connection.setDoOutput(request.body().isPresent());
-        connection.setDoInput(true);
-
-        if (connection instanceof HttpsURLConnection) {
-            HttpsURLConnection httpsConnection = (HttpsURLConnection) connection;
-            httpsConnection.setSSLSocketFactory(config.sslSocketFactory());
-            // TODO(ckozak): hostname verifier, otherwise the default is used.
-            // It's likely fine for most scenarios, but we want consistency
-            // across all channels.
-        }
-
-        if (request.body().isPresent()) {
-            Preconditions.checkArgument(
-                    endpoint.httpMethod() != HttpMethod.GET, "GET endpoints must not have a request body");
-            Preconditions.checkArgument(
-                    endpoint.httpMethod() != HttpMethod.HEAD, "HEAD endpoints must not have a request body");
-            Preconditions.checkArgument(
-                    endpoint.httpMethod() != HttpMethod.OPTIONS, "OPTIONS endpoints must not have a request body");
-            RequestBody body = request.body().get();
-            connection.setChunkedStreamingMode(1024 * 8);
-            connection.setRequestProperty("content-type", body.contentType());
-            try (OutputStream requestBodyStream = connection.getOutputStream()) {
-                body.writeTo(requestBodyStream);
-            }
-        }
-        return new HttpUrlConnectionResponse(connection);
-    }
-
-    @Override
-    public String toString() {
-        return "HttpUrlConnectionBlockingChannel{baseUrl=" + baseUrl + '}';
-    }
-
-    private static final class HttpUrlConnectionResponse implements Response {
-
-        private final HttpURLConnection connection;
-        private final int code;
-        private final ResponseAttachments attachments = ResponseAttachments.create();
-
-        HttpUrlConnectionResponse(HttpURLConnection connection) throws IOException {
-            this.connection = connection;
-            // blocks until the response is received
-            this.code = connection.getResponseCode();
-        }
-
-        @Override
-        public InputStream body() {
-            if (code >= 400) {
-                return connection.getErrorStream();
-            }
-            try {
-                return connection.getInputStream();
-            } catch (IOException e) {
-                throw new SafeRuntimeException("Failed to read response stream", e);
-            }
-        }
-
-        @Override
-        public int code() {
-            return code;
-        }
-
-        @Override
-        public ListMultimap<String, String> headers() {
-            ListMultimap<String, String> headers = MultimapBuilder.treeKeys(String.CASE_INSENSITIVE_ORDER)
-                    .arrayListValues()
-                    .build();
-            connection.getHeaderFields().forEach((headerName, headerValues) -> {
-                if (headerName != null) {
-                    headers.putAll(headerName, Iterables.filter(headerValues, Objects::nonNull));
-                }
-            });
-            return headers;
-        }
-
-        @Override
-        public Optional<String> getFirstHeader(String header) {
-            return Optional.ofNullable(connection.getHeaderField(header));
-        }
-
-        @Override
-        public ResponseAttachments attachments() {
-            return attachments;
-        }
-
-        @Override
-        public void close() {
-            try {
-                body().close();
-            } catch (IOException e) {
-                log.warn("Failed to close response", e);
-            }
-        }
-
-        @Override
-        public String toString() {
-            return "HttpUrlConnectionResponse{connection=" + connection + ", code=" + code + '}';
-        }
-    }
-}
diff --git a/dialogue-httpurlconnection-client/src/main/java/com/palantir/dialogue/httpurlconnection/HttpUrlConnectionChannels.java b/dialogue-httpurlconnection-client/src/main/java/com/palantir/dialogue/httpurlconnection/HttpUrlConnectionChannels.java
deleted file mode 100644
index de64a8ad1..000000000
--- a/dialogue-httpurlconnection-client/src/main/java/com/palantir/dialogue/httpurlconnection/HttpUrlConnectionChannels.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * (c) Copyright 2020 Palantir Technologies Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.palantir.dialogue.httpurlconnection;
-
-import com.palantir.conjure.java.client.config.ClientConfiguration;
-import com.palantir.dialogue.Channel;
-import com.palantir.dialogue.blocking.BlockingChannelAdapter;
-import com.palantir.dialogue.core.DialogueChannel;
-import com.palantir.logsafe.exceptions.SafeIllegalArgumentException;
-import java.net.MalformedURLException;
-import java.net.URL;
-
-/** Simple Channel factory which produces channels based on HttpURLConnection. */
-public final class HttpUrlConnectionChannels {
-
-    private HttpUrlConnectionChannels() {}
-
-    public static Channel create(ClientConfiguration conf) {
-        return DialogueChannel.builder()
-                .channelName("http-url-channel")
-                .clientConfiguration(conf)
-                .factory(args -> BlockingChannelAdapter.of(new HttpUrlConnectionBlockingChannel(conf, url(args.uri()))))
-                .build();
-    }
-
-    private static URL url(String uri) {
-        try {
-            return new URL(uri);
-        } catch (MalformedURLException e) {
-            throw new SafeIllegalArgumentException("Failed to parse URL", e);
-        }
-    }
-}
diff --git a/dialogue-httpurlconnection-client/src/test/java/com/palantir/dialogue/httpurlconnection/HttpUrlConnectionChannelsTest.java b/dialogue-httpurlconnection-client/src/test/java/com/palantir/dialogue/httpurlconnection/HttpUrlConnectionChannelsTest.java
deleted file mode 100644
index 940acc742..000000000
--- a/dialogue-httpurlconnection-client/src/test/java/com/palantir/dialogue/httpurlconnection/HttpUrlConnectionChannelsTest.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * (c) Copyright 2020 Palantir Technologies Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.palantir.dialogue.httpurlconnection;
-
-import com.palantir.conjure.java.client.config.ClientConfiguration;
-import com.palantir.dialogue.AbstractChannelTest;
-import com.palantir.dialogue.Channel;
-
-public final class HttpUrlConnectionChannelsTest extends AbstractChannelTest {
-
-    @Override
-    protected Channel createChannel(ClientConfiguration config) {
-        return HttpUrlConnectionChannels.create(config);
-    }
-}
diff --git a/dialogue-java-client/build.gradle b/dialogue-java-client/build.gradle
deleted file mode 100644
index 1c9cb239a..000000000
--- a/dialogue-java-client/build.gradle
+++ /dev/null
@@ -1,15 +0,0 @@
-dependencies {
-    implementation project(':dialogue-core')
-    implementation project(':dialogue-target')
-    implementation 'com.google.guava:guava'
-    implementation 'com.palantir.conjure.java.runtime:client-config'
-    implementation 'com.palantir.conjure.java.runtime:conjure-java-jackson-serialization'
-    implementation 'com.palantir.safe-logging:preconditions'
-
-    testImplementation project(':dialogue-test-common')
-    testImplementation project(':dialogue-serde')
-    testImplementation 'org.junit.jupiter:junit-jupiter'
-    implementation 'com.palantir.safe-logging:logger'
-}
-
-tasks.checkImplicitDependenciesMain.enabled = false // not published, don't care
diff --git a/dialogue-java-client/src/main/java/com/palantir/dialogue/CompletableToListenableFuture.java b/dialogue-java-client/src/main/java/com/palantir/dialogue/CompletableToListenableFuture.java
deleted file mode 100644
index 18a9ffcef..000000000
--- a/dialogue-java-client/src/main/java/com/palantir/dialogue/CompletableToListenableFuture.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * (c) Copyright 2019 Palantir Technologies Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.palantir.dialogue;
-
-import com.google.common.util.concurrent.ListenableFuture;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-class CompletableToListenableFuture<T> implements ListenableFuture<T> {
-    private final CompletableFuture<T> future;
-
-    CompletableToListenableFuture(CompletableFuture<T> future) {
-        this.future = future;
-    }
-
-    @Override
-    @SuppressWarnings("FutureReturnValueIgnored")
-    public void addListener(Runnable listener, Executor executor) {
-        future.handleAsync(
-                (_response, _throwable) -> {
-                    listener.run();
-                    return null;
-                },
-                executor);
-    }
-
-    @Override
-    public boolean cancel(boolean mayInterruptIfRunning) {
-        return future.cancel(mayInterruptIfRunning);
-    }
-
-    @Override
-    public boolean isCancelled() {
-        return future.isCancelled();
-    }
-
-    @Override
-    public boolean isDone() {
-        return future.isDone();
-    }
-
-    @Override
-    public T get() throws InterruptedException, ExecutionException {
-        return future.get();
-    }
-
-    @Override
-    public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
-        return future.get(timeout, unit);
-    }
-}
diff --git a/dialogue-java-client/src/main/java/com/palantir/dialogue/HttpChannel.java b/dialogue-java-client/src/main/java/com/palantir/dialogue/HttpChannel.java
deleted file mode 100644
index f18c90c3c..000000000
--- a/dialogue-java-client/src/main/java/com/palantir/dialogue/HttpChannel.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * (c) Copyright 2019 Palantir Technologies Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.palantir.dialogue;
-
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.MultimapBuilder;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.palantir.dialogue.core.BaseUrl;
-import com.palantir.logsafe.Preconditions;
-import com.palantir.logsafe.exceptions.SafeRuntimeException;
-import com.palantir.logsafe.logger.SafeLogger;
-import com.palantir.logsafe.logger.SafeLoggerFactory;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.http.HttpClient;
-import java.net.http.HttpRequest;
-import java.net.http.HttpResponse;
-import java.time.Duration;
-import java.util.concurrent.CompletableFuture;
-
-public final class HttpChannel implements Channel {
-    private static final SafeLogger log = SafeLoggerFactory.get(HttpChannel.class);
-
-    private final HttpClient client;
-    private final Duration requestTimeout;
-    private final BaseUrl baseUrl;
-
-    private HttpChannel(HttpClient client, URL baseUrl, Duration requestTimeout) {
-        this.client = client;
-        this.requestTimeout = requestTimeout;
-        this.baseUrl = BaseUrl.of(baseUrl);
-    }
-
-    public static HttpChannel of(HttpClient client, URL baseUrl) {
-        return new HttpChannel(client, baseUrl, Duration.ofSeconds(30));
-    }
-
-    public static HttpChannel of(HttpClient client, URL baseUrl, Duration requestTimeout) {
-        return new HttpChannel(client, baseUrl, requestTimeout);
-    }
-
-    @Override
-    public ListenableFuture<Response> execute(Endpoint endpoint, Request request) {
-        // Create base request given the URL
-        HttpRequest.Builder httpRequest = newRequestBuilder(baseUrl.render(endpoint, request));
-
-        // Fill request body and set HTTP method
-        Preconditions.checkArgument(
-                !(request.body().isPresent() && endpoint.httpMethod() == HttpMethod.GET),
-                "GET endpoints must not have a request body");
-        Preconditions.checkArgument(
-                !(request.body().isPresent() && endpoint.httpMethod() == HttpMethod.HEAD),
-                "HEAD endpoints must not have a request body");
-        Preconditions.checkArgument(
-                !(request.body().isPresent() && endpoint.httpMethod() == HttpMethod.OPTIONS),
-                "OPTIONS endpoints must not have a request body");
-        httpRequest.method(endpoint.httpMethod().name(), toBody(request));
-
-        // Fill headers
-        request.headerParams().forEach(httpRequest::header);
-
-        request.body().ifPresent(body -> httpRequest.header("content-type", body.contentType()));
-        httpRequest.timeout(requestTimeout);
-
-        // TODO(rfink): Think about repeatability/retries
-        CompletableFuture<Response> future = client.sendAsync(
-                        httpRequest.build(), HttpResponse.BodyHandlers.ofInputStream())
-                .thenApply(this::toResponse);
-
-        return new CompletableToListenableFuture<>(future);
-    }
-
-    private static HttpRequest.Builder newRequestBuilder(URL url) {
-        try {
-            return HttpRequest.newBuilder().uri(url.toURI());
-        } catch (URISyntaxException e) {
-            throw new SafeRuntimeException("Failed to construct URI, this is a bug", e);
-        }
-    }
-
-    private Response toResponse(HttpResponse<InputStream> response) {
-        return new Response() {
-
-            private final ResponseAttachments attachments = ResponseAttachments.create();
-
-            @Override
-            public InputStream body() {
-                return response.body();
-            }
-
-            @Override
-            public int code() {
-                return response.statusCode();
-            }
-
-            @Override
-            public ListMultimap<String, String> headers() {
-                ListMultimap<String, String> headers = MultimapBuilder.treeKeys(String.CASE_INSENSITIVE_ORDER)
-                        .arrayListValues()
-                        .build();
-                response.headers().map().forEach(headers::putAll);
-                return headers;
-            }
-
-            @Override
-            public ResponseAttachments attachments() {
-                return attachments;
-            }
-
-            @Override
-            public void close() {
-                try {
-                    body().close();
-                } catch (IOException e) {
-                    log.warn("Failed to close response", e);
-                }
-            }
-        };
-    }
-
-    private static HttpRequest.BodyPublisher toBody(Request request) {
-        if (request.body().isPresent()) {
-            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
-            try {
-                request.body().get().writeTo(bytes);
-            } catch (IOException e) {
-                throw new SafeRuntimeException("Failed to create a BodyPublisher", e);
-            }
-            return HttpRequest.BodyPublishers.ofByteArray(bytes.toByteArray());
-        } else {
-            return HttpRequest.BodyPublishers.noBody();
-        }
-    }
-}
diff --git a/dialogue-java-client/src/main/java/com/palantir/dialogue/JavaChannels.java b/dialogue-java-client/src/main/java/com/palantir/dialogue/JavaChannels.java
deleted file mode 100644
index 886e1371a..000000000
--- a/dialogue-java-client/src/main/java/com/palantir/dialogue/JavaChannels.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * (c) Copyright 2019 Palantir Technologies Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.palantir.dialogue;
-
-import com.palantir.conjure.java.client.config.ClientConfiguration;
-import com.palantir.dialogue.core.DialogueChannel;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.http.HttpClient;
-import java.security.GeneralSecurityException;
-import javax.net.ssl.KeyManager;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.TrustManager;
-
-public final class JavaChannels {
-
-    private static final boolean DEFAULT_ENABLE_HTTP2 = false;
-
-    private JavaChannels() {}
-
-    public static Channel create(ClientConfiguration conf) {
-        // TODO(jellis): read/write timeouts
-        // TODO(jellis): gcm cipher toggle
-        // TODO(jellis): proxy creds + mesh proxy
-        // TODO(jellis): configure node selection strategy
-        // TODO(jellis): failed url cooldown
-        // TODO(jellis): backoff slot size (possibly unnecessary)
-        // TODO(jellis): client QoS, server QoS, retries?
-
-        HttpClient client = HttpClient.newBuilder()
-                .followRedirects(HttpClient.Redirect.NORMAL)
-                .connectTimeout(conf.connectTimeout())
-                .proxy(conf.proxy())
-                .version(
-                        conf.enableHttp2().orElse(DEFAULT_ENABLE_HTTP2)
-                                ? HttpClient.Version.HTTP_2
-                                : HttpClient.Version.HTTP_1_1)
-                .sslContext(createSslContext(conf.trustManager()))
-                .build();
-
-        return DialogueChannel.builder()
-                .channelName("java-channel")
-                .clientConfiguration(conf)
-                .factory(args -> HttpChannel.of(client, url(args.uri())))
-                .build();
-    }
-
-    private static URL url(String uri) {
-        try {
-            return new URL(uri);
-        } catch (MalformedURLException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    private static SSLContext createSslContext(TrustManager trustManager) {
-        try {
-            SSLContext sslContext = SSLContext.getInstance("TLS");
-            sslContext.init(new KeyManager[] {}, new TrustManager[] {trustManager}, null);
-            return sslContext;
-        } catch (GeneralSecurityException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-}
diff --git a/dialogue-java-client/src/test/java/com/palantir/dialogue/CompletableToListenableFutureTest.java b/dialogue-java-client/src/test/java/com/palantir/dialogue/CompletableToListenableFutureTest.java
deleted file mode 100644
index 083fab2bf..000000000
--- a/dialogue-java-client/src/test/java/com/palantir/dialogue/CompletableToListenableFutureTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * (c) Copyright 2019 Palantir Technologies Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.palantir.dialogue;
-
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.MoreExecutors;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
-
-@ExtendWith(MockitoExtension.class)
-public class CompletableToListenableFutureTest {
-
-    @Mock
-    private Runnable runnable;
-
-    private CompletableFuture<String> originalFuture;
-    private CompletableToListenableFuture<String> wrappedFuture;
-
-    @BeforeEach
-    public void before() {
-        originalFuture = new CompletableFuture<>();
-        wrappedFuture = new CompletableToListenableFuture<>(originalFuture);
-    }
-
-    @Test
-    public void testAddListener() {
-        wrappedFuture.addListener(runnable, MoreExecutors.directExecutor());
-
-        verify(runnable, never()).run();
-        originalFuture.complete("done");
-        verify(runnable).run();
-    }
-
-    @Test
-    public void testCompletedExceptionally() {
-        originalFuture.completeExceptionally(new IllegalArgumentException());
-
-        assertThatThrownBy(() -> originalFuture.get())
-                .isInstanceOf(ExecutionException.class)
-                .hasCauseInstanceOf(IllegalArgumentException.class);
-        assertThatThrownBy(() -> wrappedFuture.get())
-                .isInstanceOf(ExecutionException.class)
-                .hasCauseInstanceOf(IllegalArgumentException.class);
-    }
-
-    @Test
-    public void oneOfTwoCompletedExceptionally() {
-        CompletableFuture<String> failedFuture = new CompletableFuture<>();
-        CompletableFuture<String> derivedFuture = originalFuture.thenCombine(failedFuture, String::concat);
-        ListenableFuture<String> wrappedDerivedFuture = new CompletableToListenableFuture<>(derivedFuture);
-
-        originalFuture.complete("done");
-        failedFuture.completeExceptionally(new IllegalArgumentException());
-
-        assertThatThrownBy(failedFuture::get)
-                .isInstanceOf(ExecutionException.class)
-                .hasCauseInstanceOf(IllegalArgumentException.class);
-        assertThatThrownBy(derivedFuture::get)
-                .isInstanceOf(ExecutionException.class)
-                .hasCauseInstanceOf(IllegalArgumentException.class);
-        assertThatThrownBy(wrappedDerivedFuture::get)
-                .isInstanceOf(ExecutionException.class)
-                .hasCauseInstanceOf(IllegalArgumentException.class);
-    }
-}
diff --git a/dialogue-java-client/src/test/java/com/palantir/dialogue/HttpSampleServiceClientTest.java b/dialogue-java-client/src/test/java/com/palantir/dialogue/HttpSampleServiceClientTest.java
deleted file mode 100644
index ffa9e640b..000000000
--- a/dialogue-java-client/src/test/java/com/palantir/dialogue/HttpSampleServiceClientTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * (c) Copyright 2019 Palantir Technologies Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.palantir.dialogue;
-
-import com.palantir.conjure.java.config.ssl.SslSocketFactories;
-import com.palantir.conjure.java.dialogue.serde.DefaultConjureRuntime;
-import com.palantir.dialogue.example.SampleServiceAsync;
-import com.palantir.dialogue.example.SampleServiceBlocking;
-import java.net.URL;
-import java.net.http.HttpClient;
-import java.time.Duration;
-import javax.net.ssl.SSLParameters;
-
-public final class HttpSampleServiceClientTest extends AbstractSampleServiceClientTest {
-
-    private static final ConjureRuntime runtime =
-            DefaultConjureRuntime.builder().build();
-
-    @Override
-    SampleServiceBlocking createBlockingClient(URL baseUrl, Duration timeout) {
-        Channel channel = createChannel(baseUrl, timeout);
-        return SampleServiceBlocking.of(channel, runtime);
-    }
-
-    @Override
-    SampleServiceAsync createAsyncClient(URL baseUrl, Duration timeout) {
-        Channel channel = createChannel(baseUrl, timeout);
-        return SampleServiceAsync.of(channel, runtime);
-    }
-
-    private HttpChannel createChannel(URL url, Duration timeout) {
-        SSLParameters sslConfig = new SSLParameters(ALL_CIPHER_SUITES, new String[] {"TLSv1.2"});
-        return HttpChannel.of(
-                HttpClient.newBuilder()
-                        .connectTimeout(timeout)
-                        .sslParameters(sslConfig)
-                        .sslContext(SslSocketFactories.createSslContext(SSL_CONFIG))
-                        .build(),
-                url,
-                timeout);
-    }
-}
diff --git a/dialogue-java-client/src/test/java/com/palantir/dialogue/JavaChannelsTest.java b/dialogue-java-client/src/test/java/com/palantir/dialogue/JavaChannelsTest.java
deleted file mode 100644
index cb589ede5..000000000
--- a/dialogue-java-client/src/test/java/com/palantir/dialogue/JavaChannelsTest.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * (c) Copyright 2019 Palantir Technologies Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.palantir.dialogue;
-
-import com.palantir.conjure.java.client.config.ClientConfiguration;
-
-public final class JavaChannelsTest extends AbstractChannelTest {
-
-    @Override
-    protected Channel createChannel(ClientConfiguration config) {
-        return JavaChannels.create(config);
-    }
-}
diff --git a/dialogue-java-client/src/test/resources/keyStore.jks b/dialogue-java-client/src/test/resources/keyStore.jks
deleted file mode 100644
index bba6b507b..000000000
Binary files a/dialogue-java-client/src/test/resources/keyStore.jks and /dev/null differ
diff --git a/dialogue-java-client/src/test/resources/tracing/JavaChannelsTest/requestAreTraced.log b/dialogue-java-client/src/test/resources/tracing/JavaChannelsTest/requestAreTraced.log
deleted file mode 100644
index 3c41107cf..000000000
--- a/dialogue-java-client/src/test/resources/tracing/JavaChannelsTest/requestAreTraced.log
+++ /dev/null
@@ -1,2 +0,0 @@
-{"traceId":"4be43277adec7fcb","parentSpanId":"685e41c36199d792","spanId":"1d0cffa3486685a8","type":"CLIENT_OUTGOING","operation":"Dialogue-http-request","startTimeMicroSeconds":1631051690391103,"durationNanoSeconds":7252562,"metadata":{"channel":"java-channel","mesh":"false","hostIndex":"0","outcome":"success","http.status_code":"200"}}
-{"traceId":"4be43277adec7fcb","parentSpanId":null,"spanId":"685e41c36199d792","type":"LOCAL","operation":"Dialogue: request service#endpoint","startTimeMicroSeconds":1631051690384068,"durationNanoSeconds":15207346,"metadata":{"endpointService":"service","endpointName":"endpoint","http.method":"POST","channel":"java-channel","mesh":"false","outcome":"success","http.status_code":"200"}}
diff --git a/dialogue-java-client/src/test/resources/trustStore.jks b/dialogue-java-client/src/test/resources/trustStore.jks
deleted file mode 100644
index 3a78da910..000000000
Binary files a/dialogue-java-client/src/test/resources/trustStore.jks and /dev/null differ
diff --git a/dialogue-okhttp-client/build.gradle b/dialogue-okhttp-client/build.gradle
deleted file mode 100644
index 3019d2552..000000000
--- a/dialogue-okhttp-client/build.gradle
+++ /dev/null
@@ -1,16 +0,0 @@
-dependencies {
-    implementation project(':dialogue-target')
-    implementation project(':dialogue-core')
-    implementation 'com.google.guava:guava'
-    implementation 'com.palantir.conjure.java.runtime:conjure-java-jackson-serialization'
-    implementation 'com.palantir.safe-logging:preconditions'
-    implementation 'com.squareup.okhttp3:okhttp'
-
-    testImplementation project(':dialogue-test-common')
-    testImplementation project(':dialogue-serde')
-    testImplementation project(':dialogue-core')
-    testImplementation 'org.junit.jupiter:junit-jupiter'
-    implementation 'com.palantir.safe-logging:logger'
-}
-
-tasks.checkImplicitDependenciesMain.enabled = false // not published, don't care
diff --git a/dialogue-okhttp-client/src/main/java/com/palantir/dialogue/OkHttpChannel.java b/dialogue-okhttp-client/src/main/java/com/palantir/dialogue/OkHttpChannel.java
deleted file mode 100644
index 593466dce..000000000
--- a/dialogue-okhttp-client/src/main/java/com/palantir/dialogue/OkHttpChannel.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * (c) Copyright 2019 Palantir Technologies Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.palantir.dialogue;
-
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.SettableFuture;
-import com.palantir.dialogue.core.BaseUrl;
-import com.palantir.logsafe.Preconditions;
-import java.io.IOException;
-import java.net.URL;
-import java.util.Optional;
-import javax.annotation.Nullable;
-import okhttp3.Callback;
-import okhttp3.MediaType;
-import okhttp3.OkHttpClient;
-import okhttp3.RequestBody;
-import okio.BufferedSink;
-
-public final class OkHttpChannel implements Channel {
-
-    private static final RequestBody EMPTY_REQUEST_BODY = RequestBody.create(null, new byte[] {});
-    private final OkHttpClient client;
-    private final BaseUrl baseUrl;
-
-    private OkHttpChannel(OkHttpClient client, URL baseUrl) {
-        this.client = client;
-        this.baseUrl = BaseUrl.of(baseUrl);
-    }
-
-    /** Creates a new channel with the given underlying client, baseUrl, and error decoder. Note that */
-    public static OkHttpChannel of(OkHttpClient client, URL baseUrl) {
-        return new OkHttpChannel(client, baseUrl);
-    }
-
-    private RequestBody toOkHttpBody(Optional<com.palantir.dialogue.RequestBody> body) {
-        return body.map(this::toOkHttpBody).orElse(EMPTY_REQUEST_BODY);
-    }
-
-    private RequestBody toOkHttpBody(com.palantir.dialogue.RequestBody body) {
-        return new RequestBody() {
-            @Nullable
-            @Override
-            public MediaType contentType() {
-                return MediaType.parse(body.contentType());
-            }
-
-            @Override
-            public void writeTo(BufferedSink sink) throws IOException {
-                body.writeTo(sink.outputStream());
-            }
-        };
-    }
-
-    @Override
-    public ListenableFuture<Response> execute(Endpoint endpoint, Request request) {
-        // Create base request given the URL
-        okhttp3.Request.Builder okRequest = new okhttp3.Request.Builder().url(baseUrl.render(endpoint, request));
-
-        // Fill request body and set HTTP method
-        switch (endpoint.httpMethod()) {
-            case GET:
-                Preconditions.checkArgument(!request.body().isPresent(), "GET endpoints must not have a request body");
-                okRequest = okRequest.get();
-                break;
-            case HEAD:
-                Preconditions.checkArgument(!request.body().isPresent(), "HEAD endpoints must not have a request body");
-                okRequest = okRequest.head();
-                break;
-            case OPTIONS:
-                Preconditions.checkArgument(
-                        !request.body().isPresent(), "OPTIONS endpoints must not have a request body");
-                okRequest = okRequest.method("OPTIONS", null);
-                break;
-            case POST:
-                okRequest = okRequest.post(toOkHttpBody(request.body()));
-                break;
-            case PUT:
-                okRequest = okRequest.put(toOkHttpBody(request.body()));
-                break;
-            case DELETE:
-                okRequest = okRequest.delete(
-                        request.body().isPresent() ? toOkHttpBody(request.body().get()) : null);
-                break;
-            case PATCH:
-                okRequest = okRequest.patch(toOkHttpBody(request.body()));
-                break;
-        }
-
-        // Fill headers
-        request.headerParams().forEach(okRequest::addHeader);
-
-        // TODO(rfink): Think about repeatability/retries
-
-        okhttp3.Call okCall = client.newCall(okRequest.build());
-
-        SettableFuture<Response> future = SettableFuture.create();
-        okCall.enqueue(new Callback() {
-            @Override
-            public void onFailure(okhttp3.Call _call, IOException exception) {
-                future.setException(exception);
-            }
-
-            @Override
-            public void onResponse(okhttp3.Call _call, okhttp3.Response response) {
-                future.set(OkHttpResponse.wrap(response));
-            }
-        });
-        return future;
-    }
-}
diff --git a/dialogue-okhttp-client/src/main/java/com/palantir/dialogue/OkHttpChannels.java b/dialogue-okhttp-client/src/main/java/com/palantir/dialogue/OkHttpChannels.java
deleted file mode 100644
index 3acd4bb32..000000000
--- a/dialogue-okhttp-client/src/main/java/com/palantir/dialogue/OkHttpChannels.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * (c) Copyright 2019 Palantir Technologies Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.palantir.dialogue;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.net.HttpHeaders;
-import com.google.common.util.concurrent.ThreadFactoryBuilder;
-import com.palantir.conjure.java.api.config.service.BasicCredentials;
-import com.palantir.conjure.java.client.config.CipherSuites;
-import com.palantir.conjure.java.client.config.ClientConfiguration;
-import com.palantir.dialogue.core.DialogueChannel;
-import com.palantir.logsafe.Preconditions;
-import com.palantir.logsafe.exceptions.SafeIllegalArgumentException;
-import com.palantir.logsafe.logger.SafeLogger;
-import com.palantir.logsafe.logger.SafeLoggerFactory;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.TimeUnit;
-import okhttp3.ConnectionPool;
-import okhttp3.ConnectionSpec;
-import okhttp3.Credentials;
-import okhttp3.Dispatcher;
-import okhttp3.OkHttpClient;
-import okhttp3.Protocol;
-import okhttp3.TlsVersion;
-
-public final class OkHttpChannels {
-
-    private static final SafeLogger log = SafeLoggerFactory.get(OkHttpChannels.class);
-    private static final boolean DEFAULT_ENABLE_HTTP2 = true;
-
-    private static final ThreadFactory executionThreads = new ThreadFactoryBuilder()
-            .setUncaughtExceptionHandler((_thread, uncaughtException) -> log.error(
-                    "An exception was uncaught in an execution thread. "
-                            + "This likely left a thread blocked, and is as such a serious bug "
-                            + "which requires debugging.",
-                    uncaughtException))
-            .setNameFormat("remoting-okhttp-dispatcher-%d")
-            // This diverges from the OkHttp default value, allowing the JVM to cleanly exit
-            // while idle dispatcher threads are still alive.
-            .setDaemon(true)
-            .build();
-
-    /**
-     * The {@link ExecutorService} used for the {@link Dispatcher}s of all OkHttp clients created through this class.
-     * Similar to OkHttp's default, but with two modifications:
-     *
-     * <ol>
-     *   <li>A logging uncaught exception handler
-     *   <li>Daemon threads: active request will not block JVM shutdown <b>unless</b> another non-daemon thread blocks
-     *       waiting for the result. Most of our usage falls into this category. This allows JVM shutdown to occur
-     *       cleanly without waiting a full minute after the last request completes.
-     * </ol>
-     */
-    private static final ExecutorService executionExecutor = Executors.newCachedThreadPool(executionThreads);
-
-    /** Shared dispatcher with static executor service. */
-    private static final Dispatcher dispatcher;
-
-    static {
-        dispatcher = new Dispatcher(executionExecutor);
-        // Restricting concurrency is done elsewhere in ConcurrencyLimiters and FixedLimitedChannel.
-        dispatcher.setMaxRequests(Integer.MAX_VALUE);
-        dispatcher.setMaxRequestsPerHost(Integer.MAX_VALUE);
-    }
-
-    /** Shared connection pool. */
-    private static final ConnectionPool connectionPool = new ConnectionPool(
-            1000,
-            // Most servers use a one minute keepalive for idle connections, by using a shorter keepalive on
-            // clients we can avoid race conditions where the attempts to reuse a connection as the server
-            // closes it, resulting in unnecessary I/O exceptions and retrial.
-            55,
-            TimeUnit.SECONDS);
-
-    private OkHttpChannels() {}
-
-    public static Channel create(ClientConfiguration config) {
-        Preconditions.checkArgument(
-                !config.fallbackToCommonNameVerification(), "fallback-to-common-name-verification is not supported");
-        Preconditions.checkArgument(!config.meshProxy().isPresent(), "Mesh proxy is not supported");
-        OkHttpClient.Builder builder = new OkHttpClient()
-                .newBuilder()
-                .dispatcher(dispatcher)
-                .connectionPool(connectionPool)
-                .followRedirects(false) // We implement our own redirect logic.
-                .sslSocketFactory(config.sslSocketFactory(), config.trustManager())
-                // timeouts
-                .connectTimeout(config.connectTimeout())
-                .readTimeout(config.readTimeout())
-                .writeTimeout(config.writeTimeout())
-                // proxy
-                .proxySelector(config.proxy())
-                .retryOnConnectionFailure(false);
-
-        if (config.proxyCredentials().isPresent()) {
-            BasicCredentials basicCreds = config.proxyCredentials().get();
-            final String credentials = Credentials.basic(basicCreds.username(), basicCreds.password());
-            builder.proxyAuthenticator((_route, response) -> response.request()
-                    .newBuilder()
-                    .header(HttpHeaders.PROXY_AUTHORIZATION, credentials)
-                    .build());
-        }
-
-        // cipher setup
-        builder.connectionSpecs(createConnectionSpecs(config.enableGcmCipherSuites()));
-        // gcm ciphers are required for http/2 per https://tools.ietf.org/html/rfc7540#section-9.2.2
-        // some servers fail to implement this piece of the specification, which can violate our
-        // assumptions.
-        // This check can be removed once we've migrated to TLSv1.3+
-        if (!config.enableGcmCipherSuites() || !config.enableHttp2().orElse(DEFAULT_ENABLE_HTTP2)) {
-            builder.protocols(ImmutableList.of(Protocol.HTTP_1_1));
-        }
-
-        OkHttpClient client = builder.build();
-        return DialogueChannel.builder()
-                .channelName("okhtpp-channel")
-                .clientConfiguration(config)
-                .factory(args -> OkHttpChannel.of(client, url(args.uri())))
-                .build();
-    }
-
-    private static URL url(String uri) {
-        try {
-            return new URL(uri);
-        } catch (MalformedURLException e) {
-            throw new SafeIllegalArgumentException("Failed to parse URL", e);
-        }
-    }
-
-    private static ImmutableList<ConnectionSpec> createConnectionSpecs(boolean enableGcmCipherSuites) {
-        return ImmutableList.of(
-                new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
-                        .tlsVersions(TlsVersion.TLS_1_2)
-                        .cipherSuites(
-                                enableGcmCipherSuites
-                                        ? CipherSuites.allCipherSuites()
-                                        : CipherSuites.fastCipherSuites())
-                        .build(),
-                ConnectionSpec.CLEARTEXT);
-    }
-}
diff --git a/dialogue-okhttp-client/src/main/java/com/palantir/dialogue/OkHttpResponse.java b/dialogue-okhttp-client/src/main/java/com/palantir/dialogue/OkHttpResponse.java
deleted file mode 100644
index ca201d7e4..000000000
--- a/dialogue-okhttp-client/src/main/java/com/palantir/dialogue/OkHttpResponse.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * (c) Copyright 2019 Palantir Technologies Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.palantir.dialogue;
-
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.MultimapBuilder;
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import okhttp3.ResponseBody;
-
-public final class OkHttpResponse implements Response {
-
-    private final okhttp3.Response delegate;
-    private final ResponseAttachments attachments = ResponseAttachments.create();
-
-    private OkHttpResponse(okhttp3.Response delegate) {
-        this.delegate = delegate;
-    }
-
-    /** Wraps the given OkHttp {@link okhttp3.Response} into as a {@link Response}. */
-    static OkHttpResponse wrap(okhttp3.Response delegate) {
-        return new OkHttpResponse(delegate);
-    }
-
-    @Override
-    public InputStream body() {
-        ResponseBody responseBody = delegate.body();
-        if (responseBody != null) {
-            return responseBody.byteStream();
-        }
-        return new ByteArrayInputStream(new byte[0]);
-    }
-
-    @Override
-    public int code() {
-        return delegate.code();
-    }
-
-    @Override
-    public ListMultimap<String, String> headers() {
-        ListMultimap<String, String> headers = MultimapBuilder.treeKeys(String.CASE_INSENSITIVE_ORDER)
-                .arrayListValues()
-                .build();
-        delegate.headers().toMultimap().forEach(headers::putAll);
-        return headers;
-    }
-
-    @Override
-    public ResponseAttachments attachments() {
-        return attachments;
-    }
-
-    @Override
-    public void close() {
-        delegate.close();
-    }
-}
diff --git a/dialogue-okhttp-client/src/main/java/com/palantir/dialogue/Urls.java b/dialogue-okhttp-client/src/main/java/com/palantir/dialogue/Urls.java
deleted file mode 100644
index 69c1c5905..000000000
--- a/dialogue-okhttp-client/src/main/java/com/palantir/dialogue/Urls.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * (c) Copyright 2019 Palantir Technologies Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.palantir.dialogue;
-
-import com.palantir.logsafe.Preconditions;
-import com.palantir.logsafe.exceptions.SafeRuntimeException;
-import java.net.MalformedURLException;
-import java.net.URL;
-
-/** Convenience methods for creating {@link URL}s from hosts, ports, paths, etc. */
-final class Urls {
-    private Urls() {}
-
-    static URL https(String host, int port, String path) {
-        return create("https", host, port, path);
-    }
-
-    static URL https(String host, int port) {
-        return create("https", host, port, "");
-    }
-
-    static URL http(String host, int port) {
-        return create("http", host, port, "");
-    }
-
-    static URL create(String protocol, String host, int port, String path) {
-        Preconditions.checkArgument(path.isEmpty() || path.startsWith("/"), "path must be empty or start with /");
-        try {
-            return new URL(protocol, host, port, path);
-        } catch (MalformedURLException e) {
-            throw new SafeRuntimeException("Failed to create URL", e);
-        }
-    }
-}
diff --git a/dialogue-okhttp-client/src/test/java/com/palantir/dialogue/OkHttpChannelTest.java b/dialogue-okhttp-client/src/test/java/com/palantir/dialogue/OkHttpChannelTest.java
deleted file mode 100644
index 2b92ed233..000000000
--- a/dialogue-okhttp-client/src/test/java/com/palantir/dialogue/OkHttpChannelTest.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * (c) Copyright 2019 Palantir Technologies Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.palantir.dialogue;
-
-import com.palantir.conjure.java.client.config.ClientConfiguration;
-
-public final class OkHttpChannelTest extends AbstractChannelTest {
-
-    @Override
-    protected Channel createChannel(ClientConfiguration config) {
-        return OkHttpChannels.create(config);
-    }
-}
diff --git a/dialogue-okhttp-client/src/test/java/com/palantir/dialogue/OkHttpProxyConfigTest.java b/dialogue-okhttp-client/src/test/java/com/palantir/dialogue/OkHttpProxyConfigTest.java
deleted file mode 100644
index 430d01db8..000000000
--- a/dialogue-okhttp-client/src/test/java/com/palantir/dialogue/OkHttpProxyConfigTest.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * (c) Copyright 2020 Palantir Technologies Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.palantir.dialogue;
-
-import com.palantir.conjure.java.client.config.ClientConfiguration;
-
-public final class OkHttpProxyConfigTest extends AbstractProxyConfigTest {
-    @Override
-    protected Channel create(ClientConfiguration config) {
-        return OkHttpChannels.create(config);
-    }
-}
diff --git a/dialogue-okhttp-client/src/test/java/com/palantir/dialogue/OkHttpProxyConfigTlsTest.java b/dialogue-okhttp-client/src/test/java/com/palantir/dialogue/OkHttpProxyConfigTlsTest.java
deleted file mode 100644
index cbc7c061c..000000000
--- a/dialogue-okhttp-client/src/test/java/com/palantir/dialogue/OkHttpProxyConfigTlsTest.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * (c) Copyright 2020 Palantir Technologies Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.palantir.dialogue;
-
-import com.palantir.conjure.java.client.config.ClientConfiguration;
-
-public final class OkHttpProxyConfigTlsTest extends AbstractProxyConfigTlsTest {
-    @Override
-    protected Channel create(ClientConfiguration config) {
-        return OkHttpChannels.create(config);
-    }
-}
diff --git a/dialogue-okhttp-client/src/test/java/com/palantir/dialogue/OkHttpSampleServiceClientTest.java b/dialogue-okhttp-client/src/test/java/com/palantir/dialogue/OkHttpSampleServiceClientTest.java
deleted file mode 100644
index 4eca0400a..000000000
--- a/dialogue-okhttp-client/src/test/java/com/palantir/dialogue/OkHttpSampleServiceClientTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * (c) Copyright 2019 Palantir Technologies Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.palantir.dialogue;
-
-import com.google.common.collect.ImmutableList;
-import com.palantir.conjure.java.config.ssl.SslSocketFactories;
-import com.palantir.conjure.java.dialogue.serde.DefaultConjureRuntime;
-import com.palantir.dialogue.example.SampleServiceAsync;
-import com.palantir.dialogue.example.SampleServiceBlocking;
-import java.net.URL;
-import java.time.Duration;
-import java.util.concurrent.Executors;
-import okhttp3.Dispatcher;
-import okhttp3.OkHttpClient;
-import okhttp3.Protocol;
-
-public final class OkHttpSampleServiceClientTest extends AbstractSampleServiceClientTest {
-
-    private static final ConjureRuntime runtime =
-            DefaultConjureRuntime.builder().build();
-
-    @Override
-    SampleServiceBlocking createBlockingClient(URL baseUrl, Duration timeout) {
-        Channel channel = createChannel(baseUrl, timeout);
-        return SampleServiceBlocking.of(channel, runtime);
-    }
-
-    @Override
-    SampleServiceAsync createAsyncClient(URL baseUrl, Duration timeout) {
-        Channel channel = createChannel(baseUrl, timeout);
-        return SampleServiceAsync.of(channel, runtime);
-    }
-
-    private OkHttpChannel createChannel(URL url, Duration timeout) {
-        return OkHttpChannel.of(
-                new OkHttpClient.Builder()
-                        .protocols(ImmutableList.of(Protocol.HTTP_1_1))
-                        // Execute calls on same thread so that async tests are deterministic.
-                        .dispatcher(new Dispatcher(Executors.newSingleThreadExecutor()))
-                        .callTimeout(timeout)
-                        .sslSocketFactory(
-                                SslSocketFactories.createSslSocketFactory(SSL_CONFIG),
-                                SslSocketFactories.createX509TrustManager(SSL_CONFIG))
-                        .build(),
-                url);
-    }
-}
diff --git a/dialogue-okhttp-client/src/test/java/com/palantir/dialogue/UrlsTest.java b/dialogue-okhttp-client/src/test/java/com/palantir/dialogue/UrlsTest.java
deleted file mode 100644
index cb9370b6f..000000000
--- a/dialogue-okhttp-client/src/test/java/com/palantir/dialogue/UrlsTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * (c) Copyright 2019 Palantir Technologies Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.palantir.dialogue;
-
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-import org.junit.jupiter.api.Test;
-
-public final class UrlsTest {
-
-    @Test
-    public void pathSyntax() {
-        Urls.create("https", "localhost", 1234, ""); // empty is OK
-        Urls.create("https", "localhost", 1234, "/foo"); //  starts with / is OK
-
-        // must start with /
-        assertThatThrownBy(() -> Urls.create("https", "localhost", 1234, "foo"))
-                .isInstanceOf(IllegalArgumentException.class);
-    }
-}
diff --git a/dialogue-okhttp-client/src/test/resources/keyStore.jks b/dialogue-okhttp-client/src/test/resources/keyStore.jks
deleted file mode 100644
index bba6b507b..000000000
Binary files a/dialogue-okhttp-client/src/test/resources/keyStore.jks and /dev/null differ
diff --git a/dialogue-okhttp-client/src/test/resources/tracing/OkHttpChannelTest/requestAreTraced.log b/dialogue-okhttp-client/src/test/resources/tracing/OkHttpChannelTest/requestAreTraced.log
deleted file mode 100644
index bc481db4e..000000000
--- a/dialogue-okhttp-client/src/test/resources/tracing/OkHttpChannelTest/requestAreTraced.log
+++ /dev/null
@@ -1,2 +0,0 @@
-{"traceId":"23b1cc7923e3cd6e","parentSpanId":"efc31e01e8667da5","spanId":"65d261265e96f937","type":"CLIENT_OUTGOING","operation":"Dialogue-http-request","startTimeMicroSeconds":1631051699230168,"durationNanoSeconds":7704082,"metadata":{"channel":"okhtpp-channel","mesh":"false","hostIndex":"0","outcome":"success","http.status_code":"200"}}
-{"traceId":"23b1cc7923e3cd6e","parentSpanId":null,"spanId":"efc31e01e8667da5","type":"LOCAL","operation":"Dialogue: request service#endpoint","startTimeMicroSeconds":1631051699229410,"durationNanoSeconds":9183361,"metadata":{"endpointService":"service","endpointName":"endpoint","http.method":"POST","channel":"okhtpp-channel","mesh":"false","outcome":"success","http.status_code":"200"}}
diff --git a/dialogue-okhttp-client/src/test/resources/trustStore.jks b/dialogue-okhttp-client/src/test/resources/trustStore.jks
deleted file mode 100644
index 3a78da910..000000000
Binary files a/dialogue-okhttp-client/src/test/resources/trustStore.jks and /dev/null differ
diff --git a/settings.gradle b/settings.gradle
index e088b969e..bcd9226bb 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -14,9 +14,6 @@ include 'dialogue-example'
 include 'dialogue-example:dialogue-example-dialogue'
 include 'dialogue-example:dialogue-example-objects'
 include 'dialogue-futures'
-include 'dialogue-httpurlconnection-client'
-include 'dialogue-java-client'
-include 'dialogue-okhttp-client'
 include 'dialogue-serde'
 include 'dialogue-target'
 include 'dialogue-jmh'
diff --git a/versions.lock b/versions.lock
index 714fd877c..3b6730cbc 100644
--- a/versions.lock
+++ b/versions.lock
@@ -44,8 +44,6 @@ com.palantir.tritium:tritium-core:0.30.0 (1 constraints: 3b1034a2)
 com.palantir.tritium:tritium-metrics:0.30.0 (1 constraints: 35052b3b)
 com.palantir.tritium:tritium-registry:0.30.0 (3 constraints: 8b299609)
 com.squareup:javapoet:1.13.0 (2 constraints: 2b113eee)
-com.squareup.okhttp3:okhttp:3.13.1 (2 constraints: a014ba9d)
-com.squareup.okio:okio:1.17.2 (1 constraints: 850cc309)
 commons-codec:commons-codec:1.15 (1 constraints: 0d13c328)
 io.dropwizard.metrics:metrics-core:3.2.6 (3 constraints: b325741c)
 jakarta.annotation:jakarta.annotation-api:1.3.5 (3 constraints: ee256969)
@@ -75,6 +73,8 @@ com.palantir.safe-logging:preconditions-assertj:1.19.0 (1 constraints: 3d05443b)
 com.palantir.tracing:tracing-test-utils:6.4.0 (1 constraints: 0c051536)
 com.spotify.dataenum:dataenum:1.4.1 (1 constraints: e9105ac1)
 com.squareup.okhttp3:mockwebserver:3.13.1 (1 constraints: 3a053f3b)
+com.squareup.okhttp3:okhttp:3.13.1 (2 constraints: a014ba9d)
+com.squareup.okio:okio:1.17.2 (1 constraints: 850cc309)
 commons-logging:commons-logging:1.2 (2 constraints: 8215ead1)
 de.erichseifert.vectorgraphics2d:VectorGraphics2D:0.13 (1 constraints: 8c0a80bb)
 de.rototor.pdfbox:graphics2d:0.25 (1 constraints: 8f0a84bb)