Spring Team on AOT Cache Handling, Null Safety with JSpecify, and Support Durations

MMS Founder
MMS Karsten Silz

Broadcom recently launched Spring Boot 3.5 and various Spring projects, and is working on Spring Framework 7.0 and Spring Boot 4.0 for a November 2025 debut.

Null safety in Java has recently been a special area of interest. JEP Draft 8303099, Null-Restricted and Nullable Types (Preview), is a work-in-progress and not yet a candidate for inclusion in an upcoming JDK release at this time. However, the JSpecify initiative, consisting of member organizations such as: Google (lead), Spring, JetBrains, among others, provides standard annotations for Java static analysis.

InfoQ spoke with Broadcom’s Sébastien Deleuze, Spring Framework Core Committer, and Michael Minella, Director of the Open-Source Support Spring team. They answered questions on handling the Java AOT cache, finding libraries with JSpecify support, and the recent changes to the Spring support policy.

InfoQ: Users often deploy Spring Boot applications as container images stored in a registry. However, to start applications faster with Project Leyden’s JEP 483, users must also store and distribute at least one Ahead-Of-Time (AOT) cache file for each container image. What are some best practices for that?

Sébastien Deleuze: Spring Boot is flexible here. It provides an extract command to unpack an executable JAR, which can be used with a Class Data Sharing (CDS) or AOT cache.

AOT cache will soon support an “express warmup” with JEP 515, Ahead-of-Time Method Profiling, proposed for Java 25, and JEP Draft Ahead-of-Time Code Compilation. The profiling data should come from an instance with realistic workload, potentially from production. The AOT cache will then not necessarily ship within the container image, and the integration will likely happen at the platform level. For example, we are integrating the AOT cache with Spring AOT in Tanzu Platform and Tanzu Spring to optimize Spring applications automatically.

As for shipping the cache within the container image, Spring Boot uses open-source Buildpacks to create container images. They can automatically do the training run with CDS and ship the resulting cache file within the container image. The AOT cache could ship the same way. It is worth noticing that unlike OpenJDK Project CRaC, CDS and AOT cache do not dump the raw Java process memory, avoiding the risk of leaking secrets or passwords. A best practice is to use a dedicated top-level container layer for the AOT cache, benefitting from caching the application layer and below.

InfoQ: The JSpecify initiative defines the semantics of null safety in Java and standardizes code annotations like @Nullable or @NonNull. Starting with Spring Boot 4.0, all Spring portfolio projects will eventually use JSpecify. But how does a Spring developer know which non-Spring libraries use JSpecify?

Deleuze: There is not yet a canonical place for libraries using JSpecify. But it’s an interesting idea we will share with the working group. Outside of Spring, we have seen Google, Gradle, and GraphQL adding JSpecify annotations to their libraries.

There are three key points regarding JSpecify adoption:

First, JSpecify defines three kinds of nullness: nullable (@Nullable annotation), non-null (@NonNull annotation), and unspecified (Java default). The Java default behavior applies to libraries that do not specify the nullness of their APIs. This works well when mixing null-safe and null-unsafe code, especially when null-safe APIs use null-unsafe libraries.

Second, the granularity can be more specific than a whole library. The @NullMarked annotation is typically used at the package level to declare non-null type usage by default. Nullable type usage is then marked explicitly with @Nullable. A library can progressively add null safety this way, even at the class or method level.

Finally, JSpecify has an ongoing effort to define the nullness of the JDK itself more comprehensively, as only a subset of its APIs has nullness specified.

InfoQ: The last release of a Spring Boot generation is an LTS release. Spring Boot 2.7 from May 2022 got 18 months of free updates (“OSS support”) and more than 4.5 years of paid updates (through enterprise support). Spring Boot 3.5 will only get 13 months of free updates but more than 7 years of paid ones. Why?

Michael Minella: We make minor version upgrades as simple as possible. But because a major version upgrade makes a larger ask, we have always given it more time. For instance, Spring Boot 2.7 launched in May 2022 with 18 months of OSS support and another 15 months of enterprise support. In contrast, Spring Framework 5.3, the main dependency of Spring Boot 2.7, had 50 months of OSS support and another 24 months of enterprise support. Our policy was inconsistent across the portfolio, and we wanted to do better.

So, we updated our support policy in February 2025 with two major changes. First, all support timelines now align with Spring Boot. Historically, support timelines across the portfolio depended upon the release date – different projects had different support dates. In the future, users only need to know Spring Boot’s support dates: OSS support is 13 months past the Spring Boot release it aligns with, and enterprise support is 12 months past that (both rounded to the end of the month). This standardizes support durations across the portfolio and leaves only two support timeline dates: June 30 and December 31. We are currently updating the website to make it clearer.

Second, we created a unified LTS policy instead of each project doing its own: The last minor version of a major generation, like 3.5, gets five years of additional enterprise support (on top of the 13 months of OSS support and one year regular enterprise support). This provides users with over seven years of total support timeline, the longest we have ever offered.

Over the years, our community has made it clear they need more time for a major upgrade. By providing significantly more support overall and simplifying things, we meet the community’s needs in the most sustainable way possible. Based on the feedback so far, the community agrees.


Developers can learn more about null-restricted and nullable types in this InfoQ news story and JSpecify 1.0.0 in this InfoQ news story. This InfoQ news story describes JEP 483, Ahead-of-Time Class Loading & Linking, the first deliverable of Project Leyden.

About the Author

Subscribe for MMS Newsletter

By signing up, you will receive updates about our latest information.

  • This field is for validation purposes and should be left unchanged.

Project Leyden Ships Third Option for Faster Application Start with JEP 483 in Java 24

MMS Founder
MMS Karsten Silz

In Java 24, JEP 483, Ahead-of-Time Class Loading & Linking, under the auspices of Project Leyden, starts Java applications like Spring PetClinic up to 40% faster without code changes or new application constraints. It needs a training run to build a cache file that ships with the application. With GraalVM Native Image and CRaC, applications start 95-99% faster but face more constraints. Since JVM initialization is very expensive, Leyden plans more improvements.

JEP 483 extends Java’s Class-Data Sharing (CDS). On every startup, the JVM processes the same Java classes from the application, libraries, and the JDK the same way. CDS stores the results of reading and parsing those classes in a read-only cache file. JEP 483 adds loaded and linked classes to that cache and calls it “AOT cache.”

The training run only records the AOT configuration. It’s another step to create the AOT cache. This example uses a Java compiler benchmark picked by Leyden:

java ‑XX:AOTMode=record ‑XX:AOTConfiguration=app.aotconf ‑cp JavacBenchApp.jar JavacBenchApp 50
java ‑XX:AOTMode=create ‑XX:AOTConfiguration=app.aotconf ‑XX:AOTCache=app.aot ‑cp JavacBenchApp.jar

The AOT cache app.aot file is then ready to use:

java ‑XX:AOTCache=app.aot ‑cp JavacBenchApp.jar JavacBenchApp 50

On an Apple M1 MacBook Pro, the resulting 23 MBytes AOT cache leads to a 26% faster startup. The more classes an application loads, the higher the potential speed-up from the AOT cache. That is why frameworks like Spring Boot may especially benefit from JEP 483.

Project Leyden may combine the two steps for the AOT cache creation in the future. The Quarkus framework already does that today.

The training run could be a production run, but should at least mirror production as much as possible. Using the AOT cache requires the same JDK version, operating system, CPU architecture (such as Intel x64 or ARM), class path, and Java module options as the training run, though additional classes can be used. JEP 483 cannot cache classes from user-defined class loaders and does not work with JVMTI agents that rewrite class files using ClassFileLoadHook or call the AddToBootstrapClassLoaderSearch or AddToSystemClassLoaderSearch APIs.

GraalVM Native Image is an AOT compiler ​​that moves compilation and as much initialization as possible to build time. It produces native executables that start instantly, use less RAM, and are smaller and more secure. But these executables also have principal constraints that do not affect most applications, need longer build times, have a more expensive troubleshooting process, and require more configuration. GraalVM started in Oracle Labs, but its two Java compilers may join OpenJDK.

The OpenJDK project, Coordinated Restore at Checkpoint (CRaC), takes an application memory snapshot during a training run and uses it later, similar to how JEP 483 creates and uses the AOT cache. But unlike JEP 483, CRaC only runs on Linux and requires all files and network connections to be closed before taking a snapshot and then re-opened after restoring it. That’s why it needs support from the JDK and the Java framework. While most frameworks support CRaC, only two downstream distributions of OpenJDK, Azul and Bellsoft, do. And the CRaC memory snapshot may pose security risks, as it contains passwords and credentials in clear text and is susceptible to hacking attacks.

Introduced in June 2020, the goal of Project Leyden is “to improve the startup time, time to peak performance, and footprint of Java programs.” Initially, Leyden wanted to introduce the “concept of static images to the Java Platform,” such as from GraalVM Native Image, but after two years with no public activity, it instead pivoted to optimizing the JIT compiler. JEP 483 is the first result of that pivot shipping.

In an October 2024 blog post, Juergen Hoeller, senior staff engineer and Spring Framework project lead at Broadcom, spoke of a “strategic alignment with GraalVM and Project Leyden.” JEP 483 appears to prove that: Spring and Spring Boot are the only Java frameworks mentioned, and the Spring PetClinic sample application is one of the two examples. Oracle’s Per Minborg, consulting member of technical staff, Java Core Libraries, also gave a joint presentation with Spring team member Sébastien Deleuze from Broadcom in October 2024, where unreleased improvements reduced the PetClinic startup time even further.

InfoQ reached out to learn how some Java frameworks plan to support JEP 483. Here are their answers in alphabetical order of the framework name. Some answers were edited for brevity and clarity.

The Helidon team shared a blog post with benchmarks of JEP 483, CRaC, and GraalVM Native Image. It used an application in the two Helidon flavors: Helidon SE and Helidon MP. The GraalVM Native Image speed-up below uses Profile-Guided Optimization (PGO), which also requires a training run.

Application Type JEP 483 Speed-Up CRaC Speed-Up GraalVM Native Image Speed-Up
Helidon SE 67% 95% 98%
Helidon MP 62% 98% 98%

Max Rydahl Andersen, Distinguished Engineer at Red Hat, Quarkus, and Sanne Grinovero, Quarkus founding engineer and senior principal software engineer at Red Hat, from Quarkus, said the following:

We’re glad to see Project Leyden progressing. Quarkus fully supports JEP 483 since it’s integrated into the Java VM. The biggest challenge is the training run, which can be complex – especially in containerized environments.

To simplify this, we’ve made it possible to “boot” Quarkus just before the first request and then package applications with the AOT cache. This follows a similar approach to our AppCDS support.

If your JVM supports it, you can try it with:

mvn package ‑DskipTests ‑Dquarkus.package.jar.appcds.enabled=true ‑Dquarkus.package.jar.appcds.use-aot=true

Then run:

cd target/quarkus-app/
java ‑XX:AOTCache=app.aot ‑jar quarkus-run.jar

This makes it easy to get the AOT cache, as long as you are aware of the limitations around the JDK, OS, and architecture.

This provides a noticeable boost in startup time. However, project Leyden is not complete yet, and we’re looking forward to several improvements which are not available yet.

As an example, early previews of Leyden had a significant tradeoff: While it started more efficiently, the memory consumption was also higher. And since Quarkus users care about memory, we didn’t want to recommend using it until such aspects were addressed. The Quarkus team is working very closely with the Red Hat engineers working on OpenJDK, so we are confident that such aspects are being addressed. In fact, memory consumption has already improved significantly compared to the early days, and more improvements are scheduled.

Support for custom class loaders is another big ticket on our wishlist. Speeding up classes loaded by the system class loader is great, as that accelerates the JDK initialization. But application code and Quarkus extensions are loaded by a custom class loader, so only a subset of the application currently benefits from Leyden. We’ll keep working both on our side and in collaboration with the OpenJDK team to push this further.

We’re also exploring ways to make it more practical for containerized environments, where a training run isn’t always a natural fit.

So yes, Quarkus supports Leyden and the AOT cache introduced in JEP 483, but we’re just at the beginning of a longer journey of improvements.

Sebastien Deleuze from Spring had the following to say:

The Spring team is excited that Java 24 exposes the first benefits of Project Leyden to the JVM ecosystem for wider consumption. The AOT Cache is going to supercharge CDS that is already supported by Spring Boot. We are looking forward to further evolution likely to come in future Java versions.

The Micronaut team has not responded to our request to provide a statement.

About the Author

Subscribe for MMS Newsletter

By signing up, you will receive updates about our latest information.

  • This field is for validation purposes and should be left unchanged.

InfoQ Dev Summit Munich: How to Optimize Java for the 1BRC

MMS Founder
MMS Karsten Silz

Java applications passed the 1 Billion Row Challenge (1BRC) from January 2024 in 1.5 seconds. 1BRC creator Gunnar Morling, software engineer at Decodable, detailed how the participants optimized Java at the InfoQ Dev Summit Munich 2024. General optimizations applicable to all Java applications cut the runtime from 290 seconds to 20 seconds using parallel loading/processing and optimized parsing. Getting to 1.5 seconds required niche optimizations that most Java applications should forego, except for possibly GraalVM Native Image compilation.

Each of the 1 billion rows has the name of a weather station and a single temperature ranging from -99.9°C to +99.9°C. Participants created that data file with a generator application, which was part of the challenge code. The application had to read that entire file and calculate the minimum, maximum, and average temperatures of the 400 hundred weather stations as quickly as possible. Using external libraries or caching was forbidden.

1BRC measured the official results on a 2019 AMD server processor with 128 GB RAM. The applications only used eight threads. The data file was on a RAM disk. Applications had about 113 GB RAM available, but most used much less. Each submission was tested five times, with the slowest and fastest runs discarded for consistency.

Morling wrote the baseline implementation, which took 290 seconds:

Collector
  collector = Collector.of(MeasurementAggregator:: new,
    (a, m) →> {
      a.min = Math.min(a.min, m. value) ;
      a.max = Math.max(a.max, m. value);
      a.sum += m.value;
      A.count++;
    },
    (aggl, agg2) -> {
      var res = new MeasurementAggregator();
      res.min = Math.min(aggl.min, agg2.min);
      res.max = Math.max(aggl.max, agg2.max);
      res.sum = aggl.sum + agg2.sum;
      res.count = agg1.count + agg2.count;
      return res;
    },
    agg -> {
      return new ResultRow(agg.min,
        round(agg.sum) / agg.count, agg.max);
    });

Map measurements 
  = new TreeMap(Files.Lines(Paths.get(FILE))
      .map(l -> new Measurement(l.split(";")))
      .collect(groupingBy(m →> m.station(), collector)));

System.out.println(measurements);

The 1BRC is similar to back-end processing that Java often does. That’s why its general optimizations are applicable to many Java applications.

Parallel processing meant adding a single parallel()call before the map()statement in the fourth line from the bottom. This automatically distributed the following stream operations across the eight CPU cores, cutting the runtime to 71 seconds, a 4x improvement.

Parallel loading replaces Files.Lines(Paths.get(FILE)), which turns the file into a Stream sequentially. Instead, eight threads load chunks of the file into custom memory areas with the help of JEP 442, Foreign Function & Memory API (Third Preview), delivered in Java 21. Note that the Foreign Function & Memory API was finalized with JEP 454, delivered in Java 22.

The final step of the general optimizations was changing the line reading from a string to individual bytes. Together with the parallelization, this achieved the 14.5x improvement from 290 seconds to 20 seconds.

The first step of the niche optimizations is “Single Instruction, Multiple Data (SIMD) Within a Register” (SWAR) for parsing the data. In SIMD, a processor applies the same command to multiple pieces of data, which is faster than processing it sequentially. SWAR is faster than SIMD because accessing data in CPU registers is much faster than getting it from main memory.

Custom map implementations for storing the weather station data provided another performance boost. Because there were only 400 stations, custom hash functions also saved time. Other techniques included using the Unsafe class, superscalar execution, perfect value hashing, the “spawn trick” (as characterized by Morling), and using multiple parsing loops.

Mechanical sympathy helped: the applications picked a file chunk size so that all chunks for the eight threads fit into the processor cache. And branchless programming ensured that the processor branch predictor had to discard less code.

The last two optimizations targeted how the JVM works. Its JIT compiler profiles the interpreted Java bytecode and compiles often-used methods into machine code. Additionally, the JVM creates a class list at startup and initializes the JDK. All that slows down application startup and delays reaching the top speed. The GraalVM Ahead-Of-Time (AOT) compiler Native Image moves compilation and as much initialization work as possible to build time. That produces a native executable which starts at top speed. GraalVM Native Image ships alongside new Java versions.

Using GraalVM Native Image comes at the price of some possibly showstopping constraints that do not affect most Java applications and a more expensive troubleshooting process. Many application frameworks, such as Helidon, Micronaut, Quarkus, and Spring Boot, support GraalVM Native Image. Some libraries, especially older ones, do not, which may be a showstopper. These constraints were not a factor in the 1BRC, as no external libraries were used.

Finally, the JVM garbage collector frees up unused memory. But it also uses CPU time and memory. That is why applications that did not need garbage collection used the “no-op” Epsilon garbage collector.

The niche optimizations provided a further 13x improvement down to 1.5 seconds. The fastest application with a JIT compiler took 2.367 seconds, the fastest with GraalVM Native Image finished in 1.535 seconds.

Co-author of the 1BRC winner and GraalVM founder and project lead Thomas Wuerthinger published his 10 steps of 1BRC optimizations. His baseline solution takes just 125 seconds, compared to Morling’s 290 seconds, probably because it runs on a newer 2022 Intel desktop processor. Unsurprisingly, his first step is using GraalVM Native Image. After just two steps, his solution is already down to 5.7 seconds.

Morling was positively surprised by the community that quickly formed around 1BRC. They contributed a new server, a test suite, and scripts for configuring the server environment and running the applications. Morling has not thought of a new challenge.

About the Author

Subscribe for MMS Newsletter

By signing up, you will receive updates about our latest information.

  • This field is for validation purposes and should be left unchanged.

Spring Boot 3.3 Boosts Performance, Security, and Observability

MMS Founder
MMS Karsten Silz

VMware released Spring Boot 3.3 on May 23, 2024, with significant performance, security, and observability improvements. These include Class Data Sharing (CDS) for faster startup and reduced memory usage, virtual thread support for websockets, enhanced security with JWT authentication auto-configuration, and Software Bill of Materials (SBOM) support for improved supply chain security. The upgrade also features expanded service connection options for Apache ActiveMQ and LDAP, Docker Compose support for Bitnami Container Images, and upgrades to Spring projects and third-party libraries.

The release notes include a complete list of changes and deprecations. The revamped documentation is now searchable. The minor Spring Boot 3.3.1 and 3.3.2 releases followed mid-June and mid-July, respectively.

CDS, a JVM feature that significantly reduces startup time and memory consumption, was integrated in Spring Framework 6.1 in November 2023. Spring Boot follows suit and can now easily create a CDS-friendly layout from the fat JAR with the "tools" jarmode:

java -Djarmode=tools -jar your-application.jar extract

This creates one /.jar and deposits all libraries as individual JARs into the your-application/lib folder. The application then runs with java -jar your-application/your-application.jar. The following command shows all layers:

java -Djarmode=tools -jar your-application.jar list-layers

The command java -Djarmode=tools -jar your-application.jar help offers more details.

Virtual thread support for websockets further enhances performance. However, virtual threads may not be faster than thread pools in some situations, as a recent case study showed.

Spring Boot automatically configures an instance of the Spring Security JwtAuthenticationConverter or ReactiveJwtAuthenticationConverter classes if one of these properties is set to their respective values: spring.security.oauth2.resourceserver.jwt.authority-prefix, spring.security.oauth2.resourceserver.jwt.principal-claim-name, or spring.security.oauth2.resourceserver.jwt.authorities-claim-name.

Spring Boot removed dependency management for Dropwizard Metrics on which it never directly depended upon. Spring Boot updated to the 1.x version of the Prometheus Client, up from the 0.x of previous releases, and to Micrometer 1.13.

Spring Boot now exposes SBOM with a new actuator endpoint at META-INF/sbom/bom.json or META-INF/sbom/application.cdx.json. The spring-boot-parent-starter POM has additional options for easier SBOM plugin configuration.

The new @BatchTransactionManager annotation makes custom transaction manager configuration in Spring Batch easier. Tomcat, Netty, and Undertow support Server Name Indication (SNI) for SSL. Running mvn spring-boot:run on Windows now also works with many dependencies. And resources like SSL certificates can now be loaded directly from configuration files as Base64-encoded values:

spring:
  ssl:
    bundle:
      pem:
        mybundle:
          keystore:
            certificate: "base64:LS0tLS1CRUdJTi..."
            private-key: "base64:QmFnIEF0dHJpYn..."

Spring Boot 3.3 offers native service connection support for Apache ActiveMQ Classic and Artemis components and for LDAP. Docker Compose support now also includes Bitnami Container Images alongside official images for various technologies, including Cassandra, Elasticsearch, MariaDB, MySQL, MongoDB, Neo4j, PostgreSQL, RabbitMQ, and Redis.

This release upgrades to Flyway 10.10 for automatic database structure migrations. Flyway 10 is more modular than previous versions and moved support for several databases into database-specific modules. Spring Boot now uses Infinispan 15, which has raised its Jakarta EE baseline. That’s why standard modules, such as infinispan-core, replaced several of the *-jakarta modules, such as infinispan-core-jakarta.

Other noteworthy additions include new properties for Spring Data JDBC dialect configuration (spring.data.jdbc.dialect), GraphQL websocket keep-alive configuration (spring.graphql.websocket.keep-alive), control over maximum sessions in WebFlux applications (server.reactive.session.max-sessions), and the maximum queue size of the Tomcat web server connector (server.tomcat.threads.max-queue-capacity).

Notable Spring dependency updates include Spring Security 6.3.0, Spring Session 3.3.0, Spring Data 2024.0.0, Spring GraphQL 1.3.0, Spring Integration 6.3.0, and Spring Kafka 3.2.0. Updated third-party libraries are Jackson 2.17, Hibernate 6.5, Liquibase 4.27, Oracle R2DBC 1.2.0, MySQL 8.3, Kafka 3.7, Brave 6.0, Zipkin 3.0, OpenTelemetry 1.37, and Mockito 5.11.

According to the Spring Boot release schedule, VMware plans to launch Spring Boot 3.4 on November 21, 2024, one week after the scheduled release of Spring Framework 6.2.

About the Author

Subscribe for MMS Newsletter

By signing up, you will receive updates about our latest information.

  • This field is for validation purposes and should be left unchanged.

QCon London: Netflix Saves Time and Money with Server-Driven Notifications

MMS Founder
MMS Karsten Silz

At QCon London 2024, Christopher Luu explained how Netflix uses server-driven UIs for rich notifications. This saves developer time through reuse across platforms and better testing but adds effort to maintain backward compatibility. Developers write notifications by embedding so-called Customer Lifecycle Component System (CLCS) components in JavaScript, similar to how React UIs embed HTML in JavaScript.

Notifications in Netflix apps tell users of important events, such as payment failures or promotions. Server-driven notifications allow Netflix to update the UI on the server without app updates, to share logic across the many platforms that Netflix supports, and to run A/B tests effectively. Developers can also create notifications on any platform, independent of their knowledge of platforms and programming languages.

The downsides are higher upfront costs for creating the notification framework and the need to keep the framework backward-compatible with older Netflix apps. It’s also more challenging to support offline apps and debug notifications. Finally, some developers do not enjoy non-native development.

Netflix calls a notification UMA – Universal Messaging Alert. UMA runs on TV, web, iOS, and Android. Except for the web, all these platforms require Netflix to get approval for app updates from the TV vendor, Apple, or Google. That’s where CLSC components, the server-driven UMA, save time & money: the same code runs on all platforms without app updates or approval. Still, Netflix only delivers UMA with these server-driven UIs: The apps use native, client-side UI frameworks for all other functionality.

UMA uses Hawkins, a visual design system named after the town from the Netflix show “Stranger Things”. UMA uses an existing state machine and supports multistep interstitials with forward/backward navigation, such as updating payment information. The wire protocol is JSON.

Netflix did not want to reinvent HTML for UMA, so they built CLCS as a wrapper around Hawkins. CLCS abstracts backend logic away from the apps that render the UI with native UI controls and collect user input. It offers UI components like stacks, buttons, input fields, and images, as well as effects such as dismiss or submit.

Here is a CLCS example:

export function showBox(): Screen {
  return (
    
      
        
        
      
    
  );
}

The Netflix apps are responsible for the layout of notifications, such as landscape vs. portrait, positioning, and size. The apps still send information to the server in request headers, such as the app version and device information so that UMA may take advantage of this. Developers can create new CLCS components by combining other components with templates.

UMA still has to support old versions without CLCS. Why? Because Netflix has the challenge of supporting old app versions that will never be updated: mostly phones and tablets with OS versions that Netflix doesn’t support anymore, but also TVs running older app versions. That’s where GraphQL comes in: apps use GraphQL to request UMA from the server. This allows for the introduction of new features that older clients ignore, as they still ask for the old components. Additionally, new components specify a fallback method, which builds an alternate version with CLCS baseline components. Baseline components are guaranteed to be there.

Offline devices are not a major issue today, as offline devices cannot query the server for UMA. Still, Netflix may bundle some UMA as JSON in future app versions so that some notifications still show offline.

UMA uses demo-based tests for automated tests first. Here, a demo server delivers hard-coded UMA. Because it’s clear how the Netflix app should render these, testers can take screenshots of the client app or run more specific integration tests. Netflix also runs backend template snapshot tests and traditional end-to-end tests.

Looking back, Luu listed a few things he wished he had finished earlier. These included the baseline components, a formalized testing strategy, better alignment with the design system partners, and alignment with the platforms on templates.

About the Author

Subscribe for MMS Newsletter

By signing up, you will receive updates about our latest information.

  • This field is for validation purposes and should be left unchanged.