https://github.com/apache/pulsar/pull/25275
# PIP-457: Remove support for V1 topic names and V1 Admin API
## Background knowledge
Apache Pulsar historically supported two topic naming formats:
- **V1 format**: `persistent://tenant/cluster/namespace/topic` —
includes the cluster name in the topic path
- **V2 format**: `persistent://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.
## Motivation
The continued presence of V1 topic name support imposes several costs
on the project:
1. **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.
2. **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.
3. **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.
4. **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).
5. **Confusion for new contributors and operators**: The existence of
two naming schemes and two sets of admin APIs creates unnecessary
confusion and cognitive overhead.
6. **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.
## Goals
### In Scope
- Remove all V1 Admin REST API endpoint classes and their registrations:
- `org.apache.pulsar.broker.admin.v1.PersistentTopics`
- `org.apache.pulsar.broker.admin.v1.NonPersistentTopics`
- `org.apache.pulsar.broker.admin.v1.Namespaces`
- `org.apache.pulsar.broker.admin.v1.Clusters` (if present)
- Remove V1 topic lookup endpoint:
- `org.apache.pulsar.broker.lookup.v1.TopicLookup`
- Remove V1 WebSocket handler paths
- Remove V1 (4-part) topic name parsing from `TopicName` and related classes
- Remove `isV2()` method and all conditional branching based on V1 vs
V2 topic format
- Remove `LOOKUP_PATH_V1` constant and related redirect logic
- Remove or update all tests that exercise V1 code paths
- Update CLI tools that may still reference V1 format
- Log a clear error message if a client attempts to use a V1-style
topic name, to aid migration
### Out of Scope
- Removal of the V2 Admin API in favor of V4 (that would be a separate PIP)
- Changes to the binary protocol wire format
- Metadata store migration of existing V1 topic metadata (this PIP
covers code removal; data migration would be addressed separately if
needed)
## High Level Design
The removal will be executed in a single coordinated change:
1. **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.
2. **Lookup**: Delete
`pulsar-broker/src/main/java/org/apache/pulsar/broker/lookup/v1/TopicLookup.java`
and remove its registration.
3. **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.
4. **WebSocket**: Remove V1 URI parsing paths from
`AbstractWebSocketHandler` and related classes.
5. **Tests**: Remove or convert all V1-specific test cases. Tests that
coincidentally use V1 names should be updated to V2 format.
## Detailed Design
### Admin API Removal
The following classes will be deleted:
-
`pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/PersistentTopics.java`
-
`pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/NonPersistentTopics.java`
-
`pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/Namespaces.java`
Their registration in the broker's Jersey/JAX-RS application
configuration will be removed.
### TopicName Simplification
In `pulsar-common`, the `TopicName` class will be modified:
```java
// 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.
### Lookup Simplification
The `LOOKUP_PATH_V1` constant and any conditional logic choosing
between V1/V2 redirect paths will be removed. Lookups will only use V2
paths.
### WebSocket Simplification
The `getTopic()` method in WebSocket handler classes will be
simplified to only parse V2-style URIs (`/ws/v2/...`).
## Public-facing Changes
### REST API
The following REST API paths will be **removed**:
**Persistent Topics (V1)**:
- `GET /admin/persistent/{property}/{cluster}/{namespace}` — list topics
- `GET/PUT/DELETE
/admin/persistent/{property}/{cluster}/{namespace}/{topic}/...` — all
topic operations
- `GET/PUT/DELETE
/admin/persistent/{property}/{cluster}/{namespace}/partitioned` —
partitioned topic operations
**Non-Persistent Topics (V1)**:
- `GET /admin/non-persistent/{property}/{cluster}/{namespace}` — list topics
- `GET/PUT/DELETE
/admin/non-persistent/{property}/{cluster}/{namespace}/{topic}/...` —
all topic operations
**Namespaces (V1)**:
- `GET/PUT/DELETE /admin/namespaces/{property}/{cluster}/{namespace}`
— all namespace operations
**Lookup (V1)**:
- `GET
/lookup/v2/destination/{topic-domain}/{property}/{cluster}/{namespace}/{topic}`
— topic lookup
### Binary Protocol
No changes to the binary protocol.
### Configuration
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.
### CLI
`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.
### Metrics
No metrics changes.
## Monitoring
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).
## Security Considerations
This change reduces the API attack surface by removing undocumented
but active REST endpoints. No new security considerations are
introduced.
## Backward & Forward Compatibility
### Upgrade
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:
1. Ensure all topic names in use follow the V2 format
(`persistent://tenant/namespace/topic`)
2. Ensure all Admin API clients use V2 endpoints (`/admin/v2/...`)
3. Ensure all WebSocket clients use V2 paths (`/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.
### Downgrade / Rollback
Rolling back to a prior version that supports V1 topic names will work
without issues, as no data format changes are involved.
### Geo-Replication
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.
## General Notes
### Related PIPs
- PIP-10: Remove cluster from topic name (introduced V2 naming)
- PIP-11: Short topic name (further simplified topic naming)
- PIP-48: Proposed V4 admin API (future direction for admin APIs)
### Migration Guide
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.
--
Matteo Merli
<[email protected]>