Check Ahead
Why you need it?
Background
The Seata Server has been upgraded to Spring Boot 4.0.6 (see #8137), which is built on Spring Framework 7.0.7. As a result, the server module now requires JDK 17+ (previously JDK 8). This JDK version jump introduces a deployment friction: users must ensure the target environment has the correct JDK version installed.
Problem
-
JDK dependency management burden: Currently, users who deploy the Seata Server need to manually install and manage JDK 17+ on their servers or container images. This adds complexity to deployment and operation, especially in environments where multiple Java applications with different JDK requirements coexist.
-
Startup time and resource footprint: The standard JVM-based Seata Server has non-trivial startup time and memory overhead. For cloud-native and serverless scenarios (e.g., Kubernetes pods scaling up rapidly), faster startup and lower memory consumption are highly desirable.
-
Spring Boot 4 already supports it: Spring Boot 4 (via Spring Framework 7) provides first-class AOT (Ahead-of-Time) compilation and GraalVM Native Image support out of the box. The spring-boot-maven-plugin can produce native executables with minimal configuration. However, Seata Server currently does not leverage this capability.
Benefits of Native Image
| Aspect |
JVM Mode |
Native Image Mode |
| JDK requirement |
Must install JDK 17+ |
Self-contained binary, no JDK needed |
| Startup time |
Seconds (JVM warmup) |
Milliseconds to sub-second |
| Memory footprint |
Higher (JVM overhead) |
Lower (no JVM, no class metadata) |
| Container image size |
Larger (JDK base image) |
Smaller (distroless / scratch base) |
| Deployment |
Requires Java runtime |
Single static binary |
How it could be?
Proposal: Add GraalVM Native Image packaging support to seata-server
Add a Maven profile (e.g., native) to the server/pom.xml that uses spring-boot-maven-plugin with the native classifier (or the native-maven-plugin) to produce a GraalVM native executable of the Seata Server.
High-level Steps
-
Add AOT/Native build configuration to server/pom.xml:
- Introduce a
native Maven profile that triggers GraalVM native image compilation via spring-boot-maven-plugin's process-aot goal and GraalVM's native-maven-plugin.
- Configure native image build args (e.g.,
--enable-url-protocols=http, --add-opens for reflection-heavy libraries).
-
Provide GraalVM reachability metadata (if needed):
- Some Seata components (e.g., Netty, Kryo serializer, dynamic proxies, reflection-based config loading) may require explicit GraalVM
reflect-config.json, resource-config.json, or proxy-config.json.
- Spring Boot 4's AOT engine can auto-generate most of these, but manual hints may be required for non-Spring-managed components.
-
Container image integration (optional but recommended):
- Extend the existing
jib-maven-plugin configuration (or add a Dockerfile.native) to build a minimal container image containing only the native binary (e.g., based on gcr.io/distroless/cc-debian12 or scratch).
-
CI/CD and distribution:
- Add a CI job to build and publish native binaries as release artifacts (e.g.,
seata-server-{version}-linux-amd64, seata-server-{version}-linux-arm64).
- Optionally publish native container images (e.g.,
apache/seata-server:{version}-native).
Example Pseudo-configuration
<!-- In pom.xml -->
<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<version>${spotless-maven-plugin.version}</version>
<configuration>
<json>
<includes>
<include>src/main/resources/META-INF/native-image/${project.groupId}/${project.artifactId}/*.json
</include>
</includes>
<jackson/>
</json>
</configuration>
</plugin>
<!-- In build/pom.xml -->
<properties>
<native-maven-plugin.version>1.1.3</native-maven-plugin.version>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>${native-maven-plugin.version}</version>
</plugin>
</plugins>
</pluginManagement>
</build>
<!-- In server/pom.xml -->
<profiles>
<profile>
<id>native-linux-amd64</id>
<activation>
<os>
<name>linux</name>
<arch>amd64</arch>
</os>
</activation>
<properties>
<native.platform>linux-amd64</native.platform>
</properties>
</profile>
<profile>
<id>native-linux-aarch64</id>
<activation>
<os>
<name>linux</name>
<arch>aarch64</arch>
</os>
</activation>
<properties>
<native.platform>linux-arm64</native.platform>
</properties>
</profile>
<profile>
<id>native-darwin-x86_64</id>
<activation>
<os>
<name>mac os x</name>
<arch>x86_64</arch>
</os>
</activation>
<properties>
<native.platform>darwin-amd64</native.platform>
</properties>
</profile>
<profile>
<id>native-darwin-aarch64</id>
<activation>
<os>
<name>mac os x</name>
<arch>aarch64</arch>
</os>
</activation>
<properties>
<native.platform>darwin-arm64</native.platform>
</properties>
</profile>
<profile>
<id>native-windows-amd64</id>
<activation>
<os>
<name>windows</name>
<arch>amd64</arch>
</os>
</activation>
<properties>
<native.platform>windows-amd64</native.platform>
</properties>
</profile>
<profile>
<id>native</id>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Spring-Boot-Native-Processed>true</Spring-Boot-Native-Processed>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>org.apache.seata.server.ServerApplication</mainClass>
</configuration>
<executions>
<execution>
<id>process-aot</id>
<goals>
<goal>process-aot</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<configuration>
<mainClass>org.apache.seata.server.ServerApplication</mainClass>
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
<imageName>${project.artifactId}-${project.version}-${native.platform}</imageName>
<metadataRepository>
<enabled>true</enabled>
</metadataRepository>
<buildArgs>
<arg>--enable-url-protocols=http</arg>
<arg>-H:+ReportExceptionStackTraces</arg>
</buildArgs>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</exclusion>
</exclusions>
</configuration>
<executions>
<execution>
<id>add-reachability-metadata</id>
<goals>
<goal>add-reachability-metadata</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
<profile>
<id>nativeTest</id>
<dependencies>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>org.apache.seata.server.ServerApplication</mainClass>
</configuration>
<executions>
<execution>
<id>process-test-aot</id>
<goals>
<goal>process-test-aot</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<configuration>
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
<mainClass>org.apache.seata.server.ServerApplication</mainClass>
<imageName>${project.artifactId}-${project.version}-${native.platform}</imageName>
<metadataRepository>
<enabled>true</enabled>
</metadataRepository>
<buildArgs>
<arg>--enable-url-protocols=http</arg>
<arg>-H:+ReportExceptionStackTraces</arg>
</buildArgs>
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</exclusion>
</exclusions>
</configuration>
<executions>
<execution>
<id>native-test</id>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
</profiles>
Users would then build the native image with:
mvn clean package -Pnative -pl server
And run it directly without a JDK:
./seata-server/target/seata-server
Other related information
Compatibility Considerations
-
Reflection-heavy libraries that Seata depends on may need special handling in native mode:
- Netty (used for RPC communication): Netty has existing GraalVM metadata. Spring Boot 4 should handle this via its reachability metadata repository.
- Kryo / other serializers: Serialization frameworks often rely on reflection. AOT hints or
@RegisterReflectionForBinding may be required.
- Dynamic proxies (e.g.,
java.lang.reflect.Proxy): Seata's configuration binding and interceptor chains may use proxies.
- JCommander: Command-line argument parsing may need reflection config.
-
Profile-guided optimization (PGO) can be added later to further improve native image performance.
-
Not all features need to work in native mode initially — a phased approach is acceptable:
- Phase 1: Basic server startup, configuration loading, and core transaction coordination in native mode.
- Phase 2: Full feature parity with JVM mode (all serializers, all store modes, all discovery modes).
Related Links
Check Ahead
I have searched the issues of this repository and believe that this is not a duplicate.
I am willing to try to implement this feature myself.
Why you need it?
Background
The Seata Server has been upgraded to Spring Boot 4.0.6 (see #8137), which is built on Spring Framework 7.0.7. As a result, the server module now requires JDK 17+ (previously JDK 8). This JDK version jump introduces a deployment friction: users must ensure the target environment has the correct JDK version installed.
Problem
JDK dependency management burden: Currently, users who deploy the Seata Server need to manually install and manage JDK 17+ on their servers or container images. This adds complexity to deployment and operation, especially in environments where multiple Java applications with different JDK requirements coexist.
Startup time and resource footprint: The standard JVM-based Seata Server has non-trivial startup time and memory overhead. For cloud-native and serverless scenarios (e.g., Kubernetes pods scaling up rapidly), faster startup and lower memory consumption are highly desirable.
Spring Boot 4 already supports it: Spring Boot 4 (via Spring Framework 7) provides first-class AOT (Ahead-of-Time) compilation and GraalVM Native Image support out of the box. The
spring-boot-maven-plugincan produce native executables with minimal configuration. However, Seata Server currently does not leverage this capability.Benefits of Native Image
distroless/scratchbase)How it could be?
Proposal: Add GraalVM Native Image packaging support to
seata-serverAdd a Maven profile (e.g.,
native) to theserver/pom.xmlthat usesspring-boot-maven-pluginwith thenativeclassifier (or thenative-maven-plugin) to produce a GraalVM native executable of the Seata Server.High-level Steps
Add AOT/Native build configuration to
server/pom.xml:nativeMaven profile that triggers GraalVM native image compilation viaspring-boot-maven-plugin'sprocess-aotgoal and GraalVM'snative-maven-plugin.--enable-url-protocols=http,--add-opensfor reflection-heavy libraries).Provide GraalVM reachability metadata (if needed):
reflect-config.json,resource-config.json, orproxy-config.json.Container image integration (optional but recommended):
jib-maven-pluginconfiguration (or add aDockerfile.native) to build a minimal container image containing only the native binary (e.g., based ongcr.io/distroless/cc-debian12orscratch).CI/CD and distribution:
seata-server-{version}-linux-amd64,seata-server-{version}-linux-arm64).apache/seata-server:{version}-native).Example Pseudo-configuration
Users would then build the native image with:
And run it directly without a JDK:
Other related information
Compatibility Considerations
Reflection-heavy libraries that Seata depends on may need special handling in native mode:
@RegisterReflectionForBindingmay be required.java.lang.reflect.Proxy): Seata's configuration binding and interceptor chains may use proxies.Profile-guided optimization (PGO) can be added later to further improve native image performance.
Not all features need to work in native mode initially — a phased approach is acceptable:
Related Links