Framework
dromara/dynamic-tp avatar
dromara/dynamic-tp

dromara/dynamic-tp: runtime thread pool tuning through a config center

A lightweight dynamic thread pool framework with built-in monitoring and alerting, unified third-party thread pool management, and support for popular configuration centers (Nacos, Apollo, Zookeeper, Consul, and Etcd), extensible via SPI。

4,809 stars860 forksJavaApache-2.0

At a glance

What is it?
DynamicTp extends ThreadPoolExecutor so pool parameters can change at runtime from Nacos, Apollo, Zookeeper, Consul or Etcd, with built-in metrics and alerting. It is aimed at Java teams whose thread pools are a black box until something breaks, and its cost is a config center dependency plus per-pool configuration.
Who is it for?
Adopt dromara/dynamic-tp if you already run Nacos, Apollo, Zookeeper, Consul or Etcd and you have thread pools whose core parameters you guessed at deploy time. Skip it if you cannot add a configuration center dependency, or if you only need static pools and would rather not carry the adapter and starter modules.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 40 days ago.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 26, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem DynamicTp targets: thread pools you cannot retune

ThreadPoolExecutor already exposes setCorePoolSize, setMaximumPoolSize, setKeepAliveTime, setThreadFactory, setRejectedExecutionHandler and allowCoreThreadTimeOut, plus the beforeExecute and afterExecute extension hooks. The README lists these methods as the foundation of the whole project. The gap it identifies is operational rather than technical: a pool created with parameters chosen from experience cannot be corrected without a code change and a redeployment, and during an incident there is no visibility into queue depth, active threads or rejection counts.

The README frames this as three pain points. You do not know what values to set for the core parameters. You set them by experience and discover after deployment that they need adjustment. Thread pools are a black box until something breaks. DynamicTp answers all three by moving the parameter values out of code and into a configuration center that already has high availability and push semantics, then adding monitoring and alerting on top.

The audience is Java teams running microservice architectures with a service governance stack. If you have no configuration center, the framework's premise does not hold, because the README explicitly leans on the configuration center's availability rather than building its own push mechanism.

How the config center, adapters and DtpExecutor fit together

The repository is split into modules: core, common, starter, spring, adapter, extension, logging, jvmti, benchmark, dependencies, resources and test, with a large example directory. The example folder names map directly to supported configuration centers and clouds: example-apollo, example-consul-cloud, example-etcd, example-nacos, example-nacos-cloud, example-zookeeper, example-zookeeper-cloud, example-polaris-cloud, example-huawei-cloud, plus example-adapter and example/metric. That layout is the clearest statement of the intended integration path: pick the example matching your config center and your deployment style.

The README describes the flow in four steps (add the dependency, configure, annotate, inject). At startup, thread pools are created from configuration held in the configuration center and registered in the Spring container, so business code injects an executor rather than constructing one. Because the configuration center pushes changes, parameter modification takes effect at runtime without a redeploy. The project calls this zero code intrusion, and the claim is defensible in the narrow sense that pool construction moves to configuration.

On top of the pool itself sit several pool modes. DtpExecutor is the enhanced general-purpose pool, EagerDtpExecutor is described as for IO-intensive work, ScheduledDtpExecutor for scheduled tasks, and OrderedDtpExecutor for ordered execution. There is also a compatibility path: standard JUC thread pools and Spring's ThreadPoolTaskExecutor can be brought under management by adding @DynamicTp to the @Bean definition, which matters if you already have pools you do not want to replace.

Monitoring is collected through MicroMeter, JsonLog, JMX or a Spring Boot endpoint, with more than twenty metrics covering pool, queue, task, TPS and TPxx. Alerting covers config change, thread activity, queue capacity, rejection, and task execution or wait timeout, with notification channels for WeCom, DingTalk, Feishu and email. Both monitoring and alerting are SPI-extensible, as are the config center, config parsing, task wrapping and rejection policies.

Installing DynamicTp and registering a first pool

The README does not print Maven coordinates for the artifacts, so the reliable starting point is the example directory in the repository rather than a copied snippet. The example module names tell you which one to open: example/example-nacos for a plain Nacos setup, example/example-apollo for Apollo, example/example-zookeeper for Zookeeper, and the -cloud variants for the corresponding cloud deployments. Each example carries the dependency and configuration that belongs to that configuration center.

What the README does print is the set of ThreadPoolExecutor methods the project is built on, which is worth reading before you configure anything, because those are the parameters a config-center entry will change at runtime. The block below is copied from the README's expandable section on those methods.

java
// --- Set ---
public void setCorePoolSize(int corePoolSize);                    // core pool size
public void setMaximumPoolSize(int maximumPoolSize);              // max pool size
public void setKeepAliveTime(long time, TimeUnit unit);           // thread idle keep-alive time
public void setThreadFactory(ThreadFactory threadFactory);        // thread factory
public void setRejectedExecutionHandler(RejectedExecutionHandler handler); // rejection policy
public void allowCoreThreadTimeOut(boolean value);                // allow core threads to time out

Once the dependency for your config center is in place, the README's four steps are dependency, configuration, annotation and injection. Configuration lives in the configuration center, not in the application. A pool definition there carries the core parameters and the pool name that the application will look up, and the framework registers the resulting executor as a Spring bean at startup.

For a pool you do not want to rewrite, the compatibility route is the @DynamicTp annotation on an existing @Bean definition. The README states that standard JUC thread pools and Spring ThreadPoolTaskExecutor can be managed this way, which is the shortest path from an existing codebase to managed pools.

Task context propagation is handled by implementing the TaskWrapper interface. The README names MdcTaskWrapper, TtlTaskWrapper and OpenTelemetryWrapper as examples, and describes this as stronger than Spring's built-in wrapping. If your logs or traces depend on context surviving the handoff to a worker thread, this is the piece to configure before you start tuning parameters.

Where DynamicTp is the wrong tool

The framework's core dependency is a configuration center. If your deployment has none, or if you cannot give the application a reliable connection to one at startup, the dynamic part of DynamicTp has nothing to push through. The README is explicit that it leans on the configuration center for availability rather than implementing its own delivery mechanism, so a config center outage is on your critical path for pool configuration.

A second boundary is scope. DynamicTp manages pools; it does not decide what their parameters should be. The first pain point in the README, not knowing what values to set, is only partly addressed. You still choose core size, maximum size, queue type and rejection policy. The framework makes the choice reversible at runtime, which is a real improvement over redeploying, but it is not automatic sizing.

There is also a cost to the breadth. The adapter module covers Tomcat, Jetty, Undertow, Dubbo, RocketMQ, Hystrix, gRPC, Motan, OkHttp3, Brpc, Tars, SofaRPC, RabbitMQ, Liteflow and Thrift. Each adapter is code you may pull in without needing it. A team that only wants dynamic parameters on two application-owned pools does not need most of the repository, and the module layout means you can leave the adapters out.

DynamicTp compared with Hippo4j

Hippo4j is the alternative that comes up in searches around this project, and the two differ in emphasis rather than in the problem they attack. Both make thread pool parameters adjustable at runtime through a configuration center, and both ship monitoring. DynamicTp's README positions the project as a lightweight framework layered on ThreadPoolExecutor's own set and get methods, with the configuration center doing the delivery work. The design choice is to stay close to the JDK class and add behavior around it.

Hippo4j, by contrast, is commonly described as providing a console for managing pools across applications, which changes the operational model: instead of editing configuration in Nacos or Apollo and letting it push, you work through a management interface. That is a heavier deployment but it gives a single place to see and change pools across services.

If you already run a configuration center and your team is comfortable editing configuration there, DynamicTp's approach adds less infrastructure. If you want a dedicated UI for thread pool operations across many services, the console model is the reason to look at Hippo4j instead. Neither choice is settled by feature lists; it is settled by whether you want pool management to live inside your existing configuration workflow or beside it.

Maintenance status, licence and upgrade cost

The repository is not archived, and the last push was on 2026-08-21, which is recent enough that the project is being worked on. The most recent tagged release is v1.2.2, dated 2025-05-28, following v1.2.1 on 2025-04-26 and v1.2.0 on 2025-02-17. The gap between the latest release and the latest push is worth noting: commits are landing, but the release cadence is slower than the commit cadence, so if you track the master branch you are ahead of the tagged versions.

The licence is Apache-2.0, which permits commercial use and modification and includes a patent grant. That is the permissive end of the spectrum, and it means integrating DynamicTp into a closed-source product does not by itself create a distribution obligation for your own code. This is a description of the licence identifier the repository declares, not legal advice; if your organisation has licence review requirements, the LICENSE file at the repository root is the authoritative text.

Upgrade cost is shaped by the module split. The core and starter modules carry the pool and registration logic, while adapters and configuration-center integrations are separate. A version bump that touches only an adapter you do not use should not affect you, but the SPI surface is broad (config center, config parsing, alerting, metrics collection, task wrapping, rejection policies), and any custom SPI implementation you write becomes code you maintain across upgrades. The example directory is the practical reference for what a supported configuration looks like at a given version.

Editorial conclusion

Adopt dromara/dynamic-tp if you already run Nacos, Apollo, Zookeeper, Consul or Etcd and you have thread pools whose core parameters you guessed at deploy time. Skip it if you cannot add a configuration center dependency, or if you only need static pools and would rather not carry the adapter and starter modules. Before rolling it out, verify that your configuration center version is supported and that the metrics path you plan to use (Micrometer, JsonLog, JMX or the Spring Boot endpoint) is actually wired up in your environment.

Frequently asked questions

Which configuration centers does dromara/dynamic-tp support?

The README lists Nacos, Apollo, Zookeeper, Consul, Etcd, Polaris and ServiceComb, and states that the config center integration is extensible via SPI. The example directory contains a matching example module for each of the main ones.

Can dromara/dynamic-tp manage thread pools I already created?

Yes. The README states that standard JUC thread pools and Spring ThreadPoolTaskExecutor can be brought under management by adding the @DynamicTp annotation to the @Bean definition.

What pool types does dromara/dynamic-tp provide?

The README names four modes: DtpExecutor as the enhanced general pool, EagerDtpExecutor for IO-intensive work, ScheduledDtpExecutor for scheduled tasks, and OrderedDtpExecutor for ordered execution.

Official sources

  1. dromara/dynamic-tp on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/dromara-dynamic-tp.svg)](https://hysenlabs.com/projects/dromara-dynamic-tp)