This project shows how to build "micro" applications with Spring and Spring Boot - the smallest, functional units, with the fewest dependencies and fastest start times

Open in Gitpod

Building the Apps

Build the jar:

$ ./mvnw clean install -DskipTests

Run it

$ java -jar target/micro-0.0.1-SNAPSHOT.jar
...
2018-05-23 10:03:41.776 [main] INFO  com.example.demo.DemoApplication - Started DemoApplication in 1.885 seconds (JVM running for 3.769)
...

The default app is relatively full-bodied - it uses Spring Boot and auto-configuration.

You can run the smaller apps using command line flags:

$ java -jar target/micro-0.0.1-SNAPSHOT.jar --thin.main=com.example.mini.MiniApplication
...
May 23, 2018 10:05:41 AM reactor.util.Loggers$Slf4JLogger info
INFO: Started HttpServer on /127.0.0.1:8080

The main class could be one of

Main

Description

com.example.demo.DemoApplication

(The default). Spring Boot with Webflux and full autoconfiguration

com.example.manual.ManualApplication

Spring Boot with Webflux but manually importing autoconfiguration using @ImportAutoConfiguration

com.example.boot.BootApplication

Spring Boot with Webflux and RouterFunction but no autoconfiguration

com.example.func.FuncApplication

Spring (not Boot) with Webflux and RouterFunction using manual functional bean registration

com.example.func.BuncApplication

Spring Boot with Webflux and RouterFunction using manual functional bean registration

com.example.mini.MiniApplication

Raw Spring, no autoconfiguration, but using @Configuration and RouterFunction

com.example.micro.MicroApplication

Raw Spring with no @Configuration

The thin.profile could be empty (the default) for just spring-boot-starter-webflux dependencies, or you can try jack for a more "normal" set of dependencies, e.g. with hibernate-validator, jackson, and logback. Other choices add more dependencies (e.g. actr for spring-boot-starter-actuator). You will need the "jack" profile to use actuators, so --thin.profile=actr,jack.

The apps are already systematically benchmarked here with regular JVMs: https://github.com/dsyer/spring-boot-startup-bench/blob/master/flux/README.adoc. The point of this project is just to extract them out of the JMH benchmarks, and make them easily executable as standalone apps. In the benchmarks, the "jack" profile is the default, and "jlog" is the faster reduced set of dependencies.

Benchmarks

Spring Boot 3.0.0-SNAPSHOT (Java 17):

class          method  sample beans    classes   heap   memory  median mean  range
MicroBenchmark main    empt   43.000   4081.000  6.982  33.689  0.568  0.593 0.046
MicroBenchmark main    demo   122.000  5662.000  10.669 48.869  0.849  0.901 0.085
MicroBenchmark main    manl   57.000   5035.000  9.142  44.431  0.633  0.665 0.031
MicroBenchmark main    func   44.000   3921.000  7.310  36.758  0.435  0.464 0.023
CdsBenchmark   main    empt   43.000   4161.000  7.077  24.739  0.376  0.399 0.037
CdsBenchmark   main    demo   121.000  6081.000  11.122 30.677  0.497  0.521 0.047
CdsBenchmark   main    manl   57.000   5669.000  9.871  29.126  0.393  0.410 0.021

with AOT:

class          method  sample beans    classes   heap   memory  median mean  range
MicroBenchmark main    demo   118.000  5296.000  9.448  53.407  0.785  0.814 0.026
CdsBenchmark   main    demo   118.000  5917.000  10.576 30.216  0.418  0.440 0.032

Java 19:

class         method  sample  beans   classes  heap   memory  median mean  range
CdsBenchmark  main    empt    43.000  4313.000 8.173  26.725  0.363  0.387 0.040
CdsBenchmark  main    demo    121.000 6193.000 10.888 30.987  0.496  0.523 0.032
CdsBenchmark  main    manl    57.000  5817.000 10.675 30.585  0.376  0.410 0.056

Spring Boot 2.7.3 (Java 17):

class          method sample  beans  classes   heap   memory  median mean  range
MicroBenchmark main   empt  43.000   4025.000  6.862  33.436  0.562  0.586 0.030
MicroBenchmark main   demo  122.000  5548.000  10.442 48.377  0.848  0.902 0.056
MicroBenchmark main   manl  57.000   4998.000  9.005  44.235  0.634  0.659 0.024
CdsBenchmark   main   empt  43.000   4109.000  6.917  24.652  0.365  0.391 0.033
CdsBenchmark   main   demo  121.000  6023.000  10.882 30.494  0.492  0.514 0.020
CdsBenchmark   main   manl  57.000   5626.000  9.683  29.026  0.382  0.402 0.021

Spring Boot 2.5.4 (Java 17):

class           method  sample beans   classes   heap   memory  median mean  range
MicroBenchmark  main    empt   43.000  4003.000  6.796  33.240  0.544  0.564 0.022
MicroBenchmark  main    demo   117.000 5462.000  10.169 46.527  0.817  0.870 0.095
MicroBenchmark  main    manl   58.000  4935.000  8.848  42.608  0.616  0.650 0.053
CdsBenchmark    main    empt   43.000  4094.000  6.857  24.568  0.351  0.380 0.032
CdsBenchmark    main    demo   116.000 5938.000  10.663 29.255  0.471  0.496 0.033
CdsBenchmark    main    manl   58.000  5565.000  9.513  27.864  0.385  0.396 0.012

Spring Boot 2.4.3:

class           method  sample beans   classes  heap   memory  median  mean  range
MicroBenchmark    main  empt  37.000  3492.000  5.047  36.515  0.528  0.543  0.012
MicroBenchmark    main  react  ≈ 0    2191.000  6.269  31.371  0.235  0.240  0.009
MicroBenchmark    main  micro  6.000  3240.000  7.416  40.326  0.330  0.341  0.010
MicroBenchmark    main  mini  28.000  3827.000  7.370  43.582  0.473  0.480  0.009
MicroBenchmark    main  func  45.000  3419.000  7.707  40.650  0.466  0.481  0.017
MicroBenchmark    main  bunc  46.000  4129.000  6.200  43.422  0.554  0.581  0.047
MicroBenchmark    main  cunc  52.000  4320.000  6.661  44.926  0.588  0.618  0.045
MicroBenchmark    main  boot  29.000  3435.000  6.571  41.350  0.413  0.421  0.011
MicroBenchmark    main  manl  57.000  4478.000  6.753  45.894  0.655  0.675  0.021
MicroBenchmark    main  demo  108.000 4891.000  8.656  50.341  0.818  0.830  0.019
ProfileBenchmark  main  jack  106.000 5270.000  10.205 54.235  0.851  0.874  0.029
ProfileBenchmark  main  actr  186.000 5137.000  9.889  53.202  0.928  0.965  0.049
ProfileBenchmark  main  jdbc  143.000 5119.000  9.801  52.861  0.884  0.914  0.028
ProfileBenchmark  main  actj  227.000 5375.000  11.170 55.669  1.003  1.023  0.022

JDK 18 (EA):

class         method  sample  beans  classes  heap    memory  median  mean  range
MicroBenchmark  main  empt   43.000  3991.000  6.397  32.698  0.550  0.561  0.016
MicroBenchmark  main  demo  117.000  5451.000  9.655  45.752  0.818  0.843  0.027
MicroBenchmark  main  manl   58.000  4925.000  9.328  42.846  0.624  0.643  0.019
CdsBenchmark    main  empt   43.000  4084.000  6.469  24.158  0.342  0.352  0.013
CdsBenchmark    main  demo  116.000  5932.000  10.228 28.771  0.471  0.491  0.033
CdsBenchmark    main  manl   58.000  5556.000  9.106  27.410  0.356  0.371  0.020

JDK 17:

class          method sample beans  classes    heap  memory  median  mean  range
MicroBenchmark  main  empt  37.000  3854.000  6.133  31.948  0.490  0.511  0.020
MicroBenchmark  main  demo  108.000 5262.000  9.216  44.461  0.751  0.772  0.029
MicroBenchmark  main  manl  57.000  4864.000  8.269  41.515  0.625  0.656  0.037
CdsBenchmark    main  empt  37.000  3942.000  6.184  23.773  0.302  0.325  0.017
CdsBenchmark    main  demo  107.000 5709.000  9.715  27.987  0.434  0.444  0.016
CdsBenchmark    main  manl  57.000  5470.000  8.897  26.995  0.346  0.365  0.021

Spring Boot 2.3.0:

class             method  sample  beans    classes   heap   memory  median  mean   range
MicroBenchmark    main    empt    38.000   3344.000  5.556  36.461  0.515   0.523  0.010
MicroBenchmark    main    react   ≈0       2163.000  5.995  30.828  0.223   0.228  0.007
MicroBenchmark    main    micro   6.000    3168.000  6.750  38.088  0.311   0.317  0.009
MicroBenchmark    main    mini    27.000   3731.000  6.625  41.262  0.450   0.455  0.008
MicroBenchmark    main    func    44.000   3325.000  7.117  39.532  0.447   0.455  0.008
MicroBenchmark    main    bunc    45.000   3955.000  6.859  43.211  0.505   0.521  0.023
MicroBenchmark    main    cunc    51.000   4145.000  6.057  43.402  0.545   0.571  0.046
MicroBenchmark    main    boot    28.000   3397.000  6.204  40.375  0.399   0.404  0.005
MicroBenchmark    main    manl    54.000   4301.000  6.323  44.583  0.612   0.619  0.012
MicroBenchmark    main    demo    105.000  4729.000  7.878  48.748  0.788   0.802  0.020
ProfileBenchmark  main    jack    103.000  5095.000  9.230  52.456  0.835   0.848  0.011
ProfileBenchmark  main    actr    190.000  5196.000  9.701  53.370  1.009   1.020  0.014
ProfileBenchmark  main    jdbc    140.000  5135.000  9.240  52.510  0.928   0.941  0.012
ProfileBenchmark  main    actj    230.000  5401.000  8.676  53.516  1.090   1.114  0.036

Spring Boot 2.2.1:

class           method  sample beans  classes    heap  memory  median  mean  range
MicroBenchmark    main  react ≈ 0     2166.000  5.897  30.746  0.219  0.224  0.007
MicroBenchmark    main  empt  32.000  3269.000  6.366  36.951  0.469  0.481  0.015
MicroBenchmark    main  micro 6.000   3156.000  6.638  37.913  0.305  0.312  0.008
MicroBenchmark    main  mini  27.000  3734.000  6.660  41.262  0.444  0.450  0.008
MicroBenchmark    main  func  45.000  3298.000  6.870  39.068  0.435  0.444  0.012
MicroBenchmark    main  bunc  46.000  3915.000  6.806  42.849  0.503  0.537  0.040
MicroBenchmark    main  cunc  52.000  4101.000  5.868  42.908  0.529  0.577  0.054
MicroBenchmark    main  boot  28.000  4043.000  6.012  42.109  0.387  0.395  0.011
MicroBenchmark    main  manl  53.000  4231.000  6.105  43.980  0.574  0.583  0.011
MicroBenchmark    main  demo  100.000 4671.000  7.352  47.825  0.731  0.756  0.031
ProfileBenchmark  main  jack  98.000  5431.000  9.899  54.039  0.778  0.795  0.015
ProfileBenchmark  main  actr  188.000 5704.000  9.418  55.329  0.945  0.957  0.014
ProfileBenchmark  main  jdbc  138.000 5625.000  8.262  53.747  0.880  0.980  0.137
ProfileBenchmark  main  actj  228.000 5884.000  10.758 57.704  1.030  1.142  0.116

Snapshots after 2.2.0.M4:

class         method  sample  beans  classes   heap  memory  median  mean  range
MicroBenchmark  main  empt  29.000  3272.000  6.388  36.948  0.461  0.491  0.051
MicroBenchmark  main  micro  6.000  3135.000  6.554  37.536  0.296  0.301  0.007
MicroBenchmark  main  mini  27.000  3697.000  6.546  40.860  0.426  0.438  0.011
MicroBenchmark  main  func  45.000  3317.000  6.955  39.155  0.427  0.438  0.022
MicroBenchmark  main  bunc  46.000  3922.000  6.745  42.758  0.471  0.482  0.011
MicroBenchmark  main  cunc  52.000  4082.000  5.819  42.736  0.510  0.524  0.029
MicroBenchmark  main  demo  96.000  4632.000  7.120  47.307  0.712  0.738  0.060

Earlier results:

class        method  sample  beans   classes  heap    memory  median  mean  range
MainBenchmark  main  empt  24.000   3230.000  5.103  38.769  0.546  0.555  0.018
MainBenchmark  main  jlog  80.000   3598.000  6.141  43.006  0.667  0.679  0.019
MainBenchmark  main  demo  93.000   4365.000  8.024  49.564  0.766  0.773  0.011
MainBenchmark  main  actr  174.000  5172.000  8.538  54.216  0.902  0.911  0.020
MainBenchmark  main  jdbc  131.000  5261.000  9.174  55.252  0.883  0.902  0.031
MainBenchmark  main  actj  214.000  5510.000  9.007  56.571  0.995  1.021  0.065
class         method  sample  beans  classes  heap  memory  median  mean  range
MiniBenchmark  boot   jlog  28.000  3336.000  7.082  41.949  0.588  0.597  0.014
MiniBenchmark  boot   demo  28.000  4012.000  6.508  45.566  0.703  0.710  0.011
MiniBenchmark  first  jlog  2.000   2176.000  6.556  38.574  0.416  0.418  0.004
MiniBenchmark  first  demo  2.000   2913.000  5.647  42.091  0.515  0.523  0.008
MiniBenchmark  micro  jlog  2.000   2176.000  4.608  32.886  0.336  0.345  0.013
MiniBenchmark  micro  demo  2.000   2913.000  7.318  40.454  0.438  0.451  0.016
MiniBenchmark  mini   jlog  27.000  3059.000  5.487  38.953  0.534  0.545  0.018
MiniBenchmark  mini   demo  27.000  3732.000  5.969  43.726  0.631  0.636  0.007

Building a Native Image

Checkout the "native" branch for details of how to build a native image using a buildpack and Spring Boot tooling. You can probably do it by hand with GraalVM as well if you need to, and use the thin jar to calculate its classpath for the build.