As offered on the list, here is a summary of how we restructured the Maven
modules in our
fork. The fork's groupId is com.toddysoft.db and its artifactIds start with
"toddysoft-db-";
for Apache IoTDB the same scheme would use "iotdb-" (e.g. iotdb-core-datanode).
Java packages
stay org.apache.iotdb.* in the fork.
1. The rules
------------
R1 artifactId = prefix + the module's directory path, segments joined with "-".
core/datanode -> toddysoft-db-core-datanode
core/metrics/api -> toddysoft-db-core-metrics-api
rpc/runtime -> toddysoft-db-rpc-runtime
The root POM is <prefix>-parent; each group aggregator is <prefix>-<group>.
R2 Folder names say what a module is. They drop the project prefix (iotdb-),
technology
prefixes (thrift-) and suffixes the group already says (-api in the api
group, client-
in the client group).
R3 Six groups: api, client, core, rpc, services, examples. Test and packaging
modules
(architecture-test, code-coverage, distribution, integration-test,
library-udf) stay
at the top level.
R4 Every move is a whole module: no module was split or merged, and only one
module
changed its group (service-rpc, see below).
R5 Display names follow the path too: "ToddySoft DB: <Group>: <Leaf>",
e.g. "ToddySoft DB: Core: DataNode", "ToddySoft DB: Core: Metrics: API".
R6 Not renamed: Java packages, versions, runtime names (pipe plugins such as
iotdb-thrift-sink, configuration files, Docker host names), and package
names published
outside Maven (the PyPI package apache-iotdb, the AINode Python build).
Why one rule from path to artifactId:
- Today's names grew historically and mix styles. Several don't say what the
module is:
the DataNode is published as iotdb-server, the DataNode RPC definitions as
iotdb-thrift,
the session examples as client-example.
- Many artifactIds carry no project prefix at all (rest, mqtt, pipe-api,
udf-api,
node-commons, metrics-core, calc-commons, isession, service-rpc). In a
distribution's
lib/ folder or in a user's dependency tree, rest-<version>.jar or
mqtt-<version>.jar
doesn't say it belongs to IoTDB, and generic names can clash with other
projects' jars.
- With one rule, a jar name tells you where the module lives, and a path tells
you the
jar name, with no lookup table. New modules have exactly one correct name.
- Whole-module moves keep the history: Java sources are not edited, so git
detects every
file as a rename. They also keep the translation between old and new layout a
pure
prefix mapping, which matters for anyone carrying changes across the rename.
2. The groups
-------------
iotdb-api -> api Plugin and extension APIs (UDF, trigger,
pipe, external
services). The iotdb- prefix is redundant
inside the
IoTDB repository.
iotdb-client -> client Client libraries. Same reason.
iotdb-core -> core Server-side modules. Same reason.
iotdb-protocol -> rpc These modules hold the service interfaces
and message
definitions (Thrift IDL plus generated
code) that nodes
use to call each other and that clients use
to call the
DataNode. "rpc" names the purpose, not the
IDL
technology, and is short in artifactIds.
Rejected:
"protocol" (suggests wire framing and
serialization),
"interfaces" (confused with Java
interfaces), "idl"
(names the technique), "contracts" (vague).
external-service-impl -> services The optional services (MQTT, REST) that
implement
api/external-service. "impl" says nothing
about what
they are.
example -> examples Plural, like the other group names.
Considered and rejected: moving the test and packaging modules into a build/ or
tools/
group. It would change paths in CI files and documentation for no gain in
clarity.
3. Every module
---------------
Format: old directory (old artifactId) -> new directory (new artifactId).
Modules without a
note follow the rules mechanically. Notes marked * are deliberate choices
beyond the rules.
All modules of upstream's build at the time are listed; the fork's own additions
(core/embedded, core/embedded-spring-boot) are left out.
Root
. (iotdb-parent) -> . (toddysoft-db-parent)
api
iotdb-api (iotdb-api) -> api (toddysoft-db-api)
iotdb-api/external-api (external-api) -> api/external
(toddysoft-db-api-external)
Drops the -api suffix the group already says.
iotdb-api/external-service-api (external-service-api)
-> api/external-service
(toddysoft-db-api-external-service)
Same.
iotdb-api/pipe-api (pipe-api) -> api/pipe
(toddysoft-db-api-pipe)
iotdb-api/trigger-api (trigger-api) -> api/trigger
(toddysoft-db-api-trigger)
iotdb-api/udf-api (udf-api) -> api/udf
(toddysoft-db-api-udf)
client
iotdb-client (iotdb-client) -> client (toddysoft-db-client)
iotdb-client/cli (iotdb-cli) -> client/cli
(toddysoft-db-client-cli)
iotdb-client/client-cpp (client-cpp) -> client/cpp
(toddysoft-db-client-cpp)
* The folder names the language; client- repeats the group.
iotdb-client/client-py (iotdb-python-api) -> client/python
(toddysoft-db-client-python)
* Same. The PyPI package name apache-iotdb is unchanged.
iotdb-client/client-go (git submodule) -> client/go
Path move only, .gitmodules updated.
iotdb-client/isession (isession) -> client/session-api
(toddysoft-db-client-session-api)
* The interfaces and data types of the Session API; "isession" is not a
readable
module name.
iotdb-client/jdbc (iotdb-jdbc) -> client/jdbc
(toddysoft-db-client-jdbc)
iotdb-client/session (iotdb-session) -> client/session
(toddysoft-db-client-session)
iotdb-client/subscription (iotdb-subscription) -> client/subscription
(toddysoft-db-client-subscription)
core
iotdb-core (iotdb-core) -> core (toddysoft-db-core)
iotdb-core/ainode (iotdb-ainode) -> core/ainode
(toddysoft-db-core-ainode)
iotdb-core/antlr (iotdb-antlr) -> core/grammar-tree
(toddysoft-db-core-grammar-tree)
* The tree-model SQL grammar. "antlr" names the tool, not the content,
and the
repository now has two grammars.
iotdb-core/relational-grammar (iotdb-relational-grammar)
-> core/grammar-table
(toddysoft-db-core-grammar-table)
* The table-model SQL grammar, named in parallel with grammar-tree.
iotdb-core/calc-commons (calc-commons) -> core/calc-commons
(toddysoft-db-core-calc-commons)
iotdb-core/confignode (iotdb-confignode) -> core/confignode
(toddysoft-db-core-confignode)
iotdb-core/consensus (iotdb-consensus) -> core/consensus
(toddysoft-db-core-consensus)
iotdb-core/datanode (iotdb-server) -> core/datanode
(toddysoft-db-core-datanode)
* The artifactId now says DataNode. "iotdb-server" dates from before the
ConfigNode/DataNode split and is ambiguous today.
iotdb-core/metrics (iotdb-metrics) -> core/metrics
(toddysoft-db-core-metrics)
iotdb-core/metrics/core (metrics-core) -> core/metrics/core
(toddysoft-db-core-metrics-core)
* Kept as "core". Renaming it to "impl" would clash with its package
org.apache.iotdb.metrics.core, and metrics/api already contains a
package named impl.
iotdb-core/metrics/interface (metrics-interface)
-> core/metrics/api
(toddysoft-db-core-metrics-api)
* "interface" is a Java keyword and reads oddly in names; "api" is the
common term.
iotdb-core/node-commons (node-commons) -> core/node-commons
(toddysoft-db-core-node-commons)
rpc
iotdb-protocol (iotdb-protocol) -> rpc (toddysoft-db-rpc)
iotdb-protocol/thrift-ainode (iotdb-thrift-ainode)
-> rpc/ainode
(toddysoft-db-rpc-ainode)
iotdb-protocol/thrift-commons (iotdb-thrift-commons)
-> rpc/commons
(toddysoft-db-rpc-commons)
iotdb-protocol/thrift-confignode (iotdb-thrift-confignode)
-> rpc/confignode
(toddysoft-db-rpc-confignode)
iotdb-protocol/thrift-consensus (iotdb-thrift-consensus)
-> rpc/consensus
(toddysoft-db-rpc-consensus)
iotdb-protocol/thrift-datanode (iotdb-thrift) -> rpc/datanode
(toddysoft-db-rpc-datanode)
* The old artifactId never said "datanode", although this module holds
the client and
DataNode-internal service interfaces.
iotdb-client/service-rpc (service-rpc) -> rpc/runtime
(toddysoft-db-rpc-runtime)
* The only change of group. It is the shared RPC runtime (status codes,
RpcUtils,
transports, connection exceptions). Clients and servers both use it,
and it depends
only on the rpc definitions, so it belongs with them rather than in
client.
services
external-service-impl (external-service-impl) -> services
(toddysoft-db-services)
external-service-impl/mqtt (mqtt) -> services/mqtt
(toddysoft-db-services-mqtt)
external-service-impl/rest (rest) -> services/rest
(toddysoft-db-services-rest)
external-service-impl/rest-openapi (rest-openapi)
-> services/rest-openapi
(toddysoft-db-services-rest-openapi)
The bare artifactIds mqtt, rest and rest-openapi were the clearest case
of jar names
that don't identify the project (e.g.
mqtt-<version>-jar-with-dependencies.jar).
examples
example (iotdb-examples) -> examples
(toddysoft-db-examples)
example/jdbc (jdbc-example) -> examples/jdbc
(toddysoft-db-examples-jdbc)
example/mqtt (mqtt-example) -> examples/mqtt
(toddysoft-db-examples-mqtt)
example/mqtt-customize (customize-mqtt-example)
-> examples/mqtt-customize
(toddysoft-db-examples-mqtt-customize)
example/pipe-count-point-processor (pipe-count-point-processor-example)
->
examples/pipe-count-point-processor
(toddysoft-db-examples-pipe-count-point-processor)
example/rest-java-example (rest-java-example) -> examples/rest
(toddysoft-db-examples-rest)
* Drops "-java-example", which the group already says.
example/schema (schema-example) -> examples/schema
(toddysoft-db-examples-schema)
example/session (client-example) -> examples/session
(toddysoft-db-examples-session)
* The old artifactId said "client", the folder said "session".
example/subscription (subscription-example) -> examples/subscription
(toddysoft-db-examples-subscription)
example/trigger (trigger-example) -> examples/trigger
(toddysoft-db-examples-trigger)
example/udf (udf-example) -> examples/udf
(toddysoft-db-examples-udf)
The non-Maven folders in example/ (client-cpp-example, odbc, pipe-opc-ua-sink,
rest-client-c-example) moved with the group unchanged.
Top-level test and packaging modules (folders unchanged, artifactIds prefixed)
architecture-test (iotdb-architecture-test) ->
toddysoft-db-architecture-test
code-coverage (iotdb-code-coverage) -> toddysoft-db-code-coverage
distribution (iotdb-distribution) -> toddysoft-db-distribution
integration-test (integration-test) ->
toddysoft-db-integration-test
library-udf (library-udf) -> toddysoft-db-library-udf
Derived names
Distribution archives apache-iotdb-<version>-<variant>-bin.zip ->
toddysoft-db-<version>-<variant>-bin.zip
(for IoTDB itself these would of course stay
apache-iotdb-...)
Jars in lib/ <old artifactId>-<version>.jar -> <new
artifactId>-<version>.jar
4. What to watch out for (from doing it)
-----------------------------------------
- It cannot be a global text replace. Several runtime names look like module
names but
must not change: the pipe plugins iotdb-thrift-sink / iotdb-thrift-connector,
the PyPI
package apache-iotdb, the AINode Python packaging apache-iotdb-ainode-...,
the Docker
service and host names iotdb-confignode / iotdb-datanode, configuration file
names
(iotdb-system.properties), and binary test fixtures such as udf-example.jar.
- Module names are referenced far beyond the POMs: distribution and IT assembly
descriptors, Dockerfiles, CI workflows, the C++ client's CMake paths to the
.thrift files,
the coverage scripts, README/AGENTS files, and IT framework code. One
example: the IT
framework found the DataNode jar with startsWith("iotdb-server").
- Apache RAT excludes are relative to the module being checked, so an exclude
like
**/client-cpp/test/fixtures/** has to be adapted to the new folder name as
well.
- Client artifacts are public API. iotdb-session, iotdb-jdbc, isession,
service-rpc and
the thrift artifacts are used by applications from Maven Central. Our fork
could rename
them without relocation POMs; for Apache IoTDB, renaming them would need
relocation POMs
for at least a few releases, or those artifactIds would have to keep their
names.
- We did it in one commit (moves and edits together) directly on top of an
upstream sync,
so the build was never broken in between, and kept a machine-readable
old-to-new mapping
for later syncs.
So that was just the structural changes I did ... I'm happy to whip up a PR for
javax-> jakarta, if the project is interested.
Thanks to Claude whipping up a PR from a structurally totally different
codebase is still possible ;-)
Chris
Yuan Tian <[email protected]> schrieb am Mittwoch, 4. November 2026 um
00:56:
> Hi Chris,
>
> Thanks for sharing your work. I think several of these changes could be
> valuable to the IoTDB community.
>
> For the migration from javax to Jakarta, I think this is worth exploring,
> especially to make it easier to integrate IoTDB into Spring applications.
> Could you share which modules and APIs are affected, as well as any
> compatibility considerations for existing users?
>
> Regarding direct calls within the same JVM, the current IoTDB Edge already
> runs the ConfigNode and DataNode in the same JVM, although some
> communication between them still uses RPC. The DataNode also maintains
> caches for partition information and table schemas, so I would expect the
> amount of ConfigNode communication to be relatively limited in a stable
> single-node deployment with one ConfigNode and one DataNode.
>
> It would be helpful to see some performance numbers for the direct-call
> approach. For example, which RPC paths did you replace, and how much
> improvement did you observe for representative workloads? It would also be
> useful to understand whether the changes affect any existing behavior or
> consistency guarantees.
>
> For the directory and module restructuring, could you clarify whether these
> changes are mainly intended to support the direct-call approach, or whether
> they also have independent benefits? If possible, it would be helpful to
> discuss or review the changes separately.
>
> I am particularly interested in reducing the use of singletons, as I
> believe this could help improve unit test isolation and make dependencies
> easier to replace. I would be happy to participate in this work as well. It
> would be great to learn more about your approach and see a representative
> example of the changes.
>
>
> Best regards,
>
> ------------------------
>
> Yuan Tian
>
>
>
> On Sun, Nov 1, 2026 at 6:51 PM Christofer Dutz via dev <[email protected]>
> wrote:
>
> > Hi all,
> >
> > so in the next time I'll be finally working on getting IoTDB into shape so
> > I can integrate it into my vision of an idustrial edge gateway.
> > I've so-far migrated to Java 17 (which IoTDB now also is back on par) ...
> > I've migrated from the javax to the jakarta namespace, so I can integrate
> > IoTDB into Spring applications.
> > I've introduced a "direct call if single-node and all nodes running inside
> > the same JVM".
> >
> > Now I'm currently cleaning up on the directory structure, location where
> > modules are located and their artifact-ids.
> >
> > The next big thing I have on my todo list is: "Getting rid of the
> > Singletons"
> >
> > Just wanted to know if there's any interest in any of this upstream? I
> > don't want my stuff to be a "hostile fork" and I'm happy to pass upstream
> > what I have.
> > Doesn't have to be PRs, could also post summaries of findings. But I guess
> > that's all extra work. So if there's no interest, I guess I'd rather invest
> > this into doing other things ;-)
> >
> > Chris
>