pip/pip-457.md
Apache Pulsar historically supported two topic naming formats:
persistent://tenant/cluster/namespace/topic — includes the cluster name in the topic pathpersistent://tenant/namespace/topic — omits the cluster name, making all namespaces implicitly "global"The V1 format was the original naming convention from Pulsar's early days. PIP-10 introduced V2 topic names in Pulsar 2.0 (released June 2018) by removing the cluster component, and PIP-11 further simplified naming with short topic names defaulting to persistent://public/default/. V1 topic names have been deprecated since Pulsar 2.0 — nearly 8 years ago at the time of this proposal.
The V1 naming format also implied a separate set of Admin REST API endpoints, Lookup endpoints, and WebSocket paths that include {property}/{cluster}/{namespace} in their URL structure, as opposed to the V2 paths using {tenant}/{namespace}.
These V1 APIs have been deprecated and hidden from the API documentation for many years. The V2 format has been the recommended and default format since Pulsar 2.0.
The continued presence of V1 topic name support imposes several costs on the project:
Maintenance burden: Every Admin API operation must be duplicated across V1 and V2 endpoint classes (v1.PersistentTopics, v1.NonPersistentTopics, v1.Namespaces, v1.TopicLookup alongside their V2 counterparts). Bug fixes and new features touching admin APIs must account for both code paths.
Increased attack surface: The V1 endpoints are hidden from documentation but still active and routable, creating undocumented API surface area that must be secured, tested, and maintained.
Code complexity in TopicName parsing: The TopicName class must handle both 3-part (V2) and 4-part (V1) name parsing, and the isV2() check propagates throughout the broker, lookup, and client code.
WebSocket handler complexity: WebSocket paths must support both /ws/producer/persistent/{property}/{cluster}/{namespace}/{topic} (V1) and /ws/v2/producer/persistent/{tenant}/{namespace}/{topic} (V2).
Confusion for new contributors and operators: The existence of two naming schemes and two sets of admin APIs creates unnecessary confusion and cognitive overhead.
Test matrix expansion: V1 paths must be covered by integration and unit tests, expanding the test matrix without providing value to modern deployments.
V1 topics have been deprecated since Pulsar 2.0, released in June 2018. With nearly 8 years having passed and the project now on the 4.x release line, it is time to complete this deprecation and remove V1 support entirely.
org.apache.pulsar.broker.admin.v1.PersistentTopicsorg.apache.pulsar.broker.admin.v1.NonPersistentTopicsorg.apache.pulsar.broker.admin.v1.Namespacesorg.apache.pulsar.broker.admin.v1.Clusters (if present)org.apache.pulsar.broker.lookup.v1.TopicLookupTopicName and related classesisV2() method and all conditional branching based on V1 vs V2 topic formatLOOKUP_PATH_V1 constant and related redirect logicThe removal will be executed in a single coordinated change:
Admin API: Delete the v1 package under pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/ and remove the registration of V1 REST resources from the broker's web server initialization.
Lookup: Delete pulsar-broker/src/main/java/org/apache/pulsar/broker/lookup/v1/TopicLookup.java and remove its registration.
TopicName parsing: Simplify TopicName to only accept the 3-part V2 format (domain://tenant/namespace/localName). If a 4-part name is provided, throw a clear IllegalArgumentException with a message explaining V1 names are no longer supported and how to convert.
WebSocket: Remove V1 URI parsing paths from AbstractWebSocketHandler and related classes.
Tests: Remove or convert all V1-specific test cases. Tests that coincidentally use V1 names should be updated to V2 format.
The following classes will be deleted:
pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/PersistentTopics.javapulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/NonPersistentTopics.javapulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/Namespaces.javaTheir registration in the broker's Jersey/JAX-RS application configuration will be removed.
In pulsar-common, the TopicName class will be modified:
// Before: accepts both V1 (4 parts) and V2 (3 parts)
// After: only accepts V2 (3 parts)
private TopicName(String completeTopicName) {
// ... parse domain://
String[] parts = rest.split("/", 3); // tenant/namespace/localName
if (parts.length != 3) {
throw new IllegalArgumentException(
"Invalid topic name '" + completeTopicName + "'. "
+ "Expected format: 'persistent://tenant/namespace/topic'. "
+ "V1 topic names (with cluster component) are no longer supported. "
+ "Please use the V2 format without the cluster name.");
}
this.tenant = parts[0];
this.namespace = parts[1];
this.localName = parts[2];
// cluster field removed entirely
}
The isV2() method and cluster field will be removed from TopicName. All call sites that branch on isV2() will be simplified.
The NamespaceName class will similarly be simplified to remove V1 support.
The LOOKUP_PATH_V1 constant and any conditional logic choosing between V1/V2 redirect paths will be removed. Lookups will only use V2 paths.
The getTopic() method in WebSocket handler classes will be simplified to only parse V2-style URIs (/ws/v2/...).
The following REST API paths will be removed:
Persistent Topics (V1):
GET /admin/persistent/{property}/{cluster}/{namespace} — list topicsGET/PUT/DELETE /admin/persistent/{property}/{cluster}/{namespace}/{topic}/... — all topic operationsGET/PUT/DELETE /admin/persistent/{property}/{cluster}/{namespace}/partitioned — partitioned topic operationsNon-Persistent Topics (V1):
GET /admin/non-persistent/{property}/{cluster}/{namespace} — list topicsGET/PUT/DELETE /admin/non-persistent/{property}/{cluster}/{namespace}/{topic}/... — all topic operationsNamespaces (V1):
GET/PUT/DELETE /admin/namespaces/{property}/{cluster}/{namespace} — all namespace operationsLookup (V1):
GET /lookup/v2/destination/{topic-domain}/{property}/{cluster}/{namespace}/{topic} — topic lookupNo changes to the binary protocol.
No new configuration. The broker configuration key allowV1Topics may be considered for a transitional release but is not proposed here — the removal is clean and complete.
pulsar-admin and pulsar-client CLI tools will only accept V2 topic names. Passing a V1 topic name will produce a clear error message with migration guidance.
No metrics changes.
Operators should monitor for client errors after the upgrade. Clients attempting to use V1 topic names will receive clear error responses (HTTP 404 for V1 admin paths, or client-side IllegalArgumentException for V1 topic names).
This change reduces the API attack surface by removing undocumented but active REST endpoints. No new security considerations are introduced.
This is a breaking change for any deployment still using V1 topic names or V1 Admin API paths.
Before upgrading to the version containing this change, operators must:
persistent://tenant/namespace/topic)/admin/v2/...)/ws/v2/...)The V1 format has been deprecated since Pulsar 2.0, released in June 2018 — nearly 8 years ago. Any deployment that has been maintained on a supported Pulsar version should already be using V2 format exclusively.
Rolling back to a prior version that supports V1 topic names will work without issues, as no data format changes are involved.
No impact. Geo-replication already uses V2 topic names. The cluster component in V1 topic names was originally related to replication configuration but has been decoupled since V2 was introduced.
For any users who may still be using V1 topic names, the migration is straightforward:
| V1 Format | V2 Format |
|---|---|
persistent://my-tenant/my-cluster/my-namespace/my-topic | persistent://my-tenant/my-namespace/my-topic |
/admin/persistent/my-tenant/my-cluster/my-namespace | /admin/v2/persistent/my-tenant/my-namespace |
/ws/producer/persistent/my-tenant/my-cluster/my-ns/my-topic | /ws/v2/producer/persistent/my-tenant/my-ns/my-topic |
Simply remove the cluster component from the topic name path.