<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Titouan Despierres</title>
    <description>The latest articles on DEV Community by Titouan Despierres (@aytronn).</description>
    <link>https://dev.to/aytronn</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1240152%2F8cdb44d4-437a-496d-a5f6-b6f5f94b47eb.png</url>
      <title>DEV Community: Titouan Despierres</title>
      <link>https://dev.to/aytronn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aytronn"/>
    <language>en</language>
    <item>
      <title>Scaling Java 26 AI Workloads: A 2026 Production Playbook (GitOps &amp; Kubernetes)</title>
      <dc:creator>Titouan Despierres</dc:creator>
      <pubDate>Thu, 26 Feb 2026 10:58:03 +0000</pubDate>
      <link>https://dev.to/aytronn/scaling-java-26-ai-workloads-a-2026-production-playbook-gitops-kubernetes-3ph7</link>
      <guid>https://dev.to/aytronn/scaling-java-26-ai-workloads-a-2026-production-playbook-gitops-kubernetes-3ph7</guid>
      <description>&lt;h1&gt;
  
  
  Scaling Java 26 AI Workloads: A 2026 Production Playbook (GitOps &amp;amp; Kubernetes)
&lt;/h1&gt;

&lt;p&gt;The landscape of enterprise development in early 2026 is defined by a singular challenge: moving beyond AI experimentation into &lt;strong&gt;reliable, high-scale production operations&lt;/strong&gt;. With the arrival of &lt;strong&gt;JDK 26-RC1&lt;/strong&gt;, the promise of Project Loom (Virtual Threads) and Project Panama (Foreign Function &amp;amp; Memory API) has matured into the backbone of high-performance AI integration in the Java ecosystem.&lt;/p&gt;

&lt;p&gt;This article provides a practical blueprint for architecting, building, and deploying Java 26 AI services on Kubernetes using a modern GitOps flow with GitHub Actions, GitLab CI, and Argo CD.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Java 26 Advantage: Why JDK 26 for AI?
&lt;/h2&gt;

&lt;p&gt;JDK 26 brings significant refinements that directly impact how we handle AI inference and data processing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project Panama: Native Model Interaction
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Foreign Function &amp;amp; Memory API (JEP 472)&lt;/strong&gt; is no longer "new"—it is the standard. In 2026, we use it to interface directly with C++ AI libraries (like llama.cpp or custom CUDA kernels) without the overhead of JNI.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; Reduced latency when passing large tensors between Java and native memory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safety:&lt;/strong&gt; Deterministic memory management for off-heap AI model weights.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Virtual Threads (Loom) at Scale
&lt;/h3&gt;

&lt;p&gt;For I/O-bound AI services (calling external LLM APIs like OpenAI, Anthropic, or internal vLLM clusters), Virtual Threads allow us to handle thousands of concurrent requests with a tiny footprint.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. The Build Pipeline: Containerizing JDK 26
&lt;/h2&gt;

&lt;p&gt;A production-grade pipeline must focus on security and size. We use &lt;strong&gt;multi-stage Docker builds&lt;/strong&gt; with &lt;code&gt;jlink&lt;/code&gt; to strip down the JDK to only the required modules.&lt;/p&gt;

&lt;h3&gt;
  
  
  Modern GitHub Actions Workflow
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build and Push Java AI Service&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;main&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up JDK &lt;/span&gt;&lt;span class="m"&gt;26&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-java@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;java-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;26-ea'&lt;/span&gt;
          &lt;span class="na"&gt;distribution&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;temurin'&lt;/span&gt;
          &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;maven'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build with Maven&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mvn clean package -DskipTests&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Create Custom JRE via jlink&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;$JAVA_HOME/bin/jlink \&lt;/span&gt;
            &lt;span class="s"&gt;--add-modules java.base,java.net.http,jdk.management \&lt;/span&gt;
            &lt;span class="s"&gt;--strip-debug \&lt;/span&gt;
            &lt;span class="s"&gt;--no-man-pages \&lt;/span&gt;
            &lt;span class="s"&gt;--no-header-files \&lt;/span&gt;
            &lt;span class="s"&gt;--compress=2 \&lt;/span&gt;
            &lt;span class="s"&gt;--output custom-jre&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build &amp;amp; Push Image&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;docker build -t registry.example.com/ai-service:${{ github.sha }} .&lt;/span&gt;
          &lt;span class="s"&gt;docker push registry.example.com/ai-service:${{ github.sha }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. The GitLab CI Parallel: Enterprise Readiness
&lt;/h2&gt;

&lt;p&gt;If you are on GitLab, leverage &lt;strong&gt;Environment Stop&lt;/strong&gt; and &lt;strong&gt;Security Scanning&lt;/strong&gt; as first-class citizens.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;stages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;security&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;deploy&lt;/span&gt;

&lt;span class="na"&gt;container_scanning&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;security&lt;/span&gt;
  &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aquasec/trivy:latest&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;trivy image --severity HIGH,CRITICAL registry.example.com/ai-service:$CI_COMMIT_SHA&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. Kubernetes &amp;amp; GitOps: The Argo CD Pattern
&lt;/h2&gt;

&lt;p&gt;In 2026, manual &lt;code&gt;kubectl apply&lt;/code&gt; is a relic of the past. We use &lt;strong&gt;Argo CD&lt;/strong&gt; for declarative, versioned deployments.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Kustomize Overlay
&lt;/h3&gt;

&lt;p&gt;AI workloads often require specific GPU resources. Use Kustomize to inject resource limits only for production.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# overlays/production/resources-patch.yaml&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;java-ai-service&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app&lt;/span&gt;
        &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;nvidia.com/gpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
            &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8Gi"&lt;/span&gt;
          &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2"&lt;/span&gt;
            &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;4Gi"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Argo CD Application manifest
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;argoproj.io/v1alpha1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Application&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;java-ai-service-prod&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;argocd&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;project&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
  &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;repoURL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com/org/gitops-config.git&lt;/span&gt;
    &lt;span class="na"&gt;targetRevision&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HEAD&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/java-ai-service/overlays/production&lt;/span&gt;
  &lt;span class="na"&gt;destination&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://kubernetes.default.svc&lt;/span&gt;
    &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ai-production&lt;/span&gt;
  &lt;span class="na"&gt;syncPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;automated&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;prune&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;selfHeal&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5. Observability &amp;amp; Rollout Strategies
&lt;/h2&gt;

&lt;p&gt;AI services are prone to &lt;strong&gt;model drift&lt;/strong&gt; and &lt;strong&gt;latency spikes&lt;/strong&gt;. Implementing a &lt;strong&gt;Canary Rollout&lt;/strong&gt; with Argo Rollouts is essential.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Canary?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Safety:&lt;/strong&gt; Traffic is shifted incrementally (10% -&amp;gt; 20% -&amp;gt; 50% -&amp;gt; 100%).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verification:&lt;/strong&gt; If LLM response latency exceeds 500ms or error rates climb, the system triggers an &lt;strong&gt;automatic rollback&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# rollout.yaml (Argo Rollouts)&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;argoproj.io/v1alpha1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Rollout&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;java-ai-service&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;canary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;setWeight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;pause&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;duration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;5m&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;setWeight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;pause&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;duration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;10m&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  6. Adoption Strategy: How to Start
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Audit your JDK version:&lt;/strong&gt; If you are still on JDK 17, skip 21 and target &lt;strong&gt;JDK 25 (LTS)&lt;/strong&gt; or &lt;strong&gt;26 (Latest)&lt;/strong&gt; to leverage Panama.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Move to GitOps:&lt;/strong&gt; Stop using CI pipelines to "push" to K8s. Use them to update a GitOps repo that Argo CD "pulls" from.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Isolate AI Logic:&lt;/strong&gt; Keep your "Orchestration" (Java) separate from your "Inference" (C++/Python/CUDA) using Panama or gRPC for maximum stability.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Java's role in the AI era is not as the model-training language, but as the &lt;strong&gt;reliable platform engineering language&lt;/strong&gt;. By combining JDK 26's native efficiencies with Kubernetes-native GitOps, we build systems that are not just smart, but production-hardened.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; #java #kubernetes #ai #devops&lt;/p&gt;

</description>
      <category>java</category>
      <category>kubernetes</category>
      <category>ai</category>
      <category>devops</category>
    </item>
    <item>
      <title>Optimizing Java AI Architectures for 2026: JDK 26, HTTP/3, and GitOps Control Planes</title>
      <dc:creator>Titouan Despierres</dc:creator>
      <pubDate>Tue, 24 Feb 2026 14:53:25 +0000</pubDate>
      <link>https://dev.to/aytronn/optimizing-java-ai-architectures-for-2026-jdk-26-http3-and-gitops-control-planes-48b5</link>
      <guid>https://dev.to/aytronn/optimizing-java-ai-architectures-for-2026-jdk-26-http3-and-gitops-control-planes-48b5</guid>
      <description>&lt;h1&gt;
  
  
  Optimizing Java AI Architectures for 2026: JDK 26, HTTP/3, and GitOps Control Planes
&lt;/h1&gt;

&lt;p&gt;As we move into early 2026, the intersection of Java, Cloud Native, and AI is undergoing a massive shift. With &lt;strong&gt;JDK 26&lt;/strong&gt; entering its Final Release Candidate (RC) phase and the stabilization of &lt;strong&gt;HTTP/3&lt;/strong&gt; within the Java ecosystem, the way we build, deploy, and observe high-performance AI-driven services has fundamentally changed.&lt;/p&gt;

&lt;p&gt;In this guide, we’ll explore how to leverage the latest Java capabilities alongside modern DevOps patterns (GitLab/GitHub, Argo CD, and Kubernetes) to build a production-grade AI inference gateway.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Java Platform Shift: JDK 26 and HTTP/3
&lt;/h2&gt;

&lt;p&gt;JDK 26 is not just another incremental update. Two key JEPs are changing the game for AI and high-frequency workloads:&lt;/p&gt;

&lt;h3&gt;
  
  
  JEP 517: HTTP/3 for the HTTP Client API
&lt;/h3&gt;

&lt;p&gt;In AI architectures, low latency is everything. HTTP/3 (QUIC) solves the head-of-line blocking issues common in HTTP/2. For an AI Gateway that orchestrates calls between multiple LLM providers (OpenAI, Anthropic, or local Ollama instances), this means a more resilient and faster connection.&lt;/p&gt;

&lt;h3&gt;
  
  
  JEP 516: Ahead-of-Time (AOT) Object Caching
&lt;/h3&gt;

&lt;p&gt;This allows the JVM to "warm up" object graphs before execution. For AI applications using heavy frameworks like LangChain4j or Spring AI, reducing the cold-start latency of your Kubernetes pods is a significant win.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. CI/CD for AI Services: Unified Pipelines
&lt;/h2&gt;

&lt;p&gt;Whether you are on GitLab or GitHub, your pipeline needs to handle more than just a &lt;code&gt;mvn package&lt;/code&gt;. You need deep integration with your Kubernetes observability stack.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: GitHub Actions for Java AI Deployment
&lt;/h3&gt;

&lt;p&gt;Here is a modernized workflow that uses &lt;strong&gt;GitHub Actions&lt;/strong&gt; to build a JDK 26 container and notify &lt;strong&gt;Argo CD&lt;/strong&gt; via GitOps.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy Java AI Gateway&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;main"&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up JDK &lt;/span&gt;&lt;span class="m"&gt;26&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-java@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;java-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;26'&lt;/span&gt;
          &lt;span class="na"&gt;distribution&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;temurin'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build with Maven&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mvn clean package -DskipTests&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build and Push Docker Image&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;docker build -t my-org/ai-gateway:${{ github.sha }} .&lt;/span&gt;
          &lt;span class="s"&gt;docker push my-org/ai-gateway:${{ github.sha }}&lt;/span&gt;

  &lt;span class="na"&gt;gitops-update&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Update Kustomize Manifest&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;git clone https://github.com/my-org/gitops-infra.git&lt;/span&gt;
          &lt;span class="s"&gt;cd gitops-infra/apps/ai-gateway&lt;/span&gt;
          &lt;span class="s"&gt;kustomize edit set image ai-gateway=my-org/ai-gateway:${{ github.sha }}&lt;/span&gt;
          &lt;span class="s"&gt;git config user.name "GitOps Bot"&lt;/span&gt;
          &lt;span class="s"&gt;git config user.email "bot@my-org.com"&lt;/span&gt;
          &lt;span class="s"&gt;git commit -am "chore: update ai-gateway image to ${{ github.sha }}"&lt;/span&gt;
          &lt;span class="s"&gt;git push&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. Kubernetes &amp;amp; GitOps: The Argo CD Pattern
&lt;/h2&gt;

&lt;p&gt;Manual &lt;code&gt;kubectl apply&lt;/code&gt; is a relic of the past. In 2026, &lt;strong&gt;Argo CD&lt;/strong&gt; is the standard for ensuring your cluster state matches your repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practical Argo CD Application Manifest
&lt;/h3&gt;

&lt;p&gt;To ensure high availability and observability, your Argo CD Application should reference a structured Helm or Kustomize layout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;argoproj.io/v1alpha1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Application&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ai-gateway-prod&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;argocd&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;project&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
  &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;repoURL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://github.com/my-org/gitops-infra.git'&lt;/span&gt;
    &lt;span class="na"&gt;targetRevision&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HEAD&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/ai-gateway/overlays/prod&lt;/span&gt;
  &lt;span class="na"&gt;destination&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://kubernetes.default.svc'&lt;/span&gt;
    &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ai-apps&lt;/span&gt;
  &lt;span class="na"&gt;syncPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;automated&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;prune&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;selfHeal&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;syncOptions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;CreateNamespace=true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. Production Observability: The Feedback Loop
&lt;/h2&gt;

&lt;p&gt;Deploying is only half the battle. For AI services, you must monitor &lt;strong&gt;TTFT (Time To First Token)&lt;/strong&gt; and &lt;strong&gt;Inference Latency&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Using &lt;strong&gt;Kubernetes Horizontal Pod Autoscaler (HPA)&lt;/strong&gt; based on custom metrics (like active HTTP/3 streams) is essential.&lt;/p&gt;

&lt;h3&gt;
  
  
  K8s Manifest for Advanced Scaling
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;autoscaling/v2&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HorizontalPodAutoscaler&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ai-gateway-hpa&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;scaleTargetRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
    &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ai-gateway&lt;/span&gt;
  &lt;span class="na"&gt;minReplicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
  &lt;span class="na"&gt;maxReplicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
  &lt;span class="na"&gt;metrics&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Resource&lt;/span&gt;
    &lt;span class="na"&gt;resource&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cpu&lt;/span&gt;
      &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Utilization&lt;/span&gt;
        &lt;span class="na"&gt;averageUtilization&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;70&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5. Summary &amp;amp; Adoption Strategy
&lt;/h2&gt;

&lt;p&gt;To adopt these patterns in your organization:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Test JDK 26 RC:&lt;/strong&gt; Use it for non-critical internal tools to benchmark JEP 517 (HTTP/3) benefits.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Standardize GitOps:&lt;/strong&gt; Move your CI/CD pipelines to a push-to-git model instead of direct cluster access.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Observability First:&lt;/strong&gt; Don't ship AI features without tracing (OpenTelemetry is your friend here).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;JDK 26 provides the performance, and GitOps provides the control. Combined, they form the bedrock of reliable AI systems in 2026.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What’s your experience with Java and AI in production? Let's discuss in the comments!&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  java #kubernetes #devops #ai
&lt;/h1&gt;

</description>
      <category>java</category>
      <category>kubernetes</category>
      <category>devops</category>
      <category>ai</category>
    </item>
    <item>
      <title>Optimizing Java AI Workloads on Kubernetes: A 2026 GitOps Playbook</title>
      <dc:creator>Titouan Despierres</dc:creator>
      <pubDate>Tue, 24 Feb 2026 14:50:55 +0000</pubDate>
      <link>https://dev.to/aytronn/optimizing-java-ai-workloads-on-kubernetes-a-2026-gitops-playbook-175h</link>
      <guid>https://dev.to/aytronn/optimizing-java-ai-workloads-on-kubernetes-a-2026-gitops-playbook-175h</guid>
      <description>&lt;h1&gt;
  
  
  Optimizing Java AI Workloads on Kubernetes: A 2026 GitOps Playbook
&lt;/h1&gt;

&lt;p&gt;As we move further into 2026, the intersection of &lt;strong&gt;Java 25&lt;/strong&gt;, &lt;strong&gt;Agentic AI&lt;/strong&gt;, and &lt;strong&gt;Cloud Native infrastructure&lt;/strong&gt; has matured into a robust ecosystem. For DevOps and Platform Engineers, the challenge is no longer just "getting it to run," but optimizing for inference performance, cost-efficiency, and secure delivery via modern CI/CD patterns.&lt;/p&gt;

&lt;p&gt;In this guide, we’ll explore how to architect a production-grade pipeline for a Java-based AI service using GitHub Actions, GitLab CI, and GitOps with Argo CD on Kubernetes.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Java 25 Edge: Native Memory &amp;amp; AI Frameworks
&lt;/h2&gt;

&lt;p&gt;With the recent JEPs in Java 25 (Project Loom and Panama refinements), Java has become a formidable platform for AI inference. The key is managing &lt;strong&gt;Off-Heap memory&lt;/strong&gt; correctly for large language models or vector embeddings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practical Pattern: Resource Management in K8s
&lt;/h3&gt;

&lt;p&gt;When running a Spring AI or LangChain4j application, your JVM memory footprint is split. You must account for the &lt;code&gt;MaxDirectMemorySize&lt;/code&gt; when setting your Kubernetes limits.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Kubernetes Deployment Snippet&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;java-ai-service&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;acme/java-ai-app:latest&lt;/span&gt;
    &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2Gi"&lt;/span&gt;
        &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1000m"&lt;/span&gt;
      &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;4Gi"&lt;/span&gt; &lt;span class="c1"&gt;# Leave headroom for Native Memory&lt;/span&gt;
    &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;JAVA_OPTS&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-XX:MaxRAMPercentage=75.0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-XX:MaxDirectMemorySize=1G"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. CI/CD: The Dual-Platform Strategy
&lt;/h2&gt;

&lt;p&gt;Whether you are on GitLab or GitHub, your pipeline should focus on &lt;strong&gt;OCI compliance&lt;/strong&gt; and &lt;strong&gt;automated vulnerability scanning&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  GitHub Actions: Agentic Workflow Integration
&lt;/h3&gt;

&lt;p&gt;GitHub's 2026 updates introduced enhanced agentic workflows. Here is a modern &lt;code&gt;release.yml&lt;/code&gt; for a Java AI project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build and Push&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;v*'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up JDK &lt;/span&gt;&lt;span class="m"&gt;25&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-java@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;java-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;25'&lt;/span&gt;
          &lt;span class="na"&gt;distribution&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;temurin'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build with Maven&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mvn clean package -DskipTests&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build and Push OCI Image&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/build-push-action@v5&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;user/java-ai:latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  GitLab CI: Multi-Project Pipelines for Platform Engineering
&lt;/h3&gt;

&lt;p&gt;In GitLab, the "Platform Engineering" approach uses shared templates to enforce security.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# .gitlab-ci.yml&lt;/span&gt;
&lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;project&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;platform/templates'&lt;/span&gt;
    &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/java/default-pipeline.yml'&lt;/span&gt;

&lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;DOCKER_IMAGE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG&lt;/span&gt;

&lt;span class="na"&gt;stages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;deploy-preview&lt;/span&gt;

&lt;span class="na"&gt;deploy:preview&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deploy-preview&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;kustomize edit set image app=$DOCKER_IMAGE&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;git commit -am "chore:update preview image"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;git push origin HEAD&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. GitOps with Argo CD: The Progressive Rollout
&lt;/h2&gt;

&lt;p&gt;Continuous Deployment isn't enough; you need &lt;strong&gt;Observability-driven rollouts&lt;/strong&gt;. Argo CD Rollouts allow us to perform Canary deployments for our AI services.&lt;/p&gt;

&lt;h3&gt;
  
  
  Argo CD Rollout Manifest
&lt;/h3&gt;

&lt;p&gt;Instead of a standard &lt;code&gt;Deployment&lt;/code&gt;, use a &lt;code&gt;Rollout&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;argoproj.io/v1alpha1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Rollout&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ai-inference-engine&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
  &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;canary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;setWeight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;pause&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;duration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;10m&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;setWeight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;pause&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;duration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;5m&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# ... standard pod template&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. Production Strategy: Observability &amp;amp; Rollback
&lt;/h2&gt;

&lt;p&gt;For AI workloads, traditional HTTP health checks are insufficient. You need to monitor &lt;strong&gt;Inference Latency&lt;/strong&gt; and &lt;strong&gt;Token Usage&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key recommendations:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Security:&lt;/strong&gt; Use Chainguard or Wolfi-based "distroless" images to reduce the attack surface of your Java containers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rollback:&lt;/strong&gt; Always keep your GitOps repository as the "Source of Truth". If a model performs poorly in production (hallucinations or latency spikes), a simple &lt;code&gt;git revert&lt;/code&gt; on your Argo CD repo is your safest rollback mechanism.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adoption:&lt;/strong&gt; Start with &lt;strong&gt;Internal Developer Portals (IDP)&lt;/strong&gt; like Backstage to template these complex AI + K8s manifests for your developers.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Java's renaissance in the AI era is driven by its stability and the power of Kubernetes. By leveraging GitHub Actions for rapid CI, GitLab for enterprise governance, and Argo CD for GitOps, you create a resilient platform ready for the scale of 2026.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is your current bottleneck in Java AI deployments? Let's discuss in the comments!&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  java #kubernetes #devops #ai
&lt;/h1&gt;

</description>
      <category>java</category>
      <category>kubernetes</category>
      <category>devops</category>
      <category>ai</category>
    </item>
    <item>
      <title>Shipping Java AI Services on Kubernetes in 2026: A Practical CI/CD Playbook (GitHub Actions + GitLab CI + Argo CD)</title>
      <dc:creator>Titouan Despierres</dc:creator>
      <pubDate>Sun, 22 Feb 2026 13:25:34 +0000</pubDate>
      <link>https://dev.to/aytronn/shipping-java-ai-services-on-kubernetes-in-2026-a-practical-cicd-playbook-github-actions--578h</link>
      <guid>https://dev.to/aytronn/shipping-java-ai-services-on-kubernetes-in-2026-a-practical-cicd-playbook-github-actions--578h</guid>
      <description>&lt;h1&gt;
  
  
  Shipping Java AI Services on Kubernetes in 2026: A Practical CI/CD Playbook (GitHub Actions + GitLab CI + Argo CD)
&lt;/h1&gt;

&lt;p&gt;If you build production systems with Java and Kubernetes, 2026 feels different from even two years ago.&lt;/p&gt;

&lt;p&gt;The stack is more capable, but also less forgiving:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java moved forward fast (JDK 21 in production, JDK 25 now on the adoption table)&lt;/li&gt;
&lt;li&gt;AI features are no longer “labs-only” and now sit in real SLAs&lt;/li&gt;
&lt;li&gt;Kubernetes keeps evolving APIs and operational defaults&lt;/li&gt;
&lt;li&gt;CI/CD shifted from “just run tests” to provenance, policy, and progressive delivery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article is a field playbook: what changed, why it’s better (or what trade-offs you pay), and how to adopt safely in production.&lt;/p&gt;




&lt;h2&gt;
  
  
  1) Java in 2026: LTS strategy is now an architecture decision
&lt;/h2&gt;

&lt;p&gt;Many teams are on Java 17 or 21. The strategic question now is not &lt;em&gt;if&lt;/em&gt; you move, but &lt;em&gt;how often&lt;/em&gt; you want to absorb JVM/runtime changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  What changed
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JDK 21&lt;/strong&gt; proved itself in production (virtual threads adoption matured, better startup/perf ergonomics).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JDK 25 (LTS)&lt;/strong&gt; is now the next serious target for teams wanting fresh runtime optimizations and longer runway.&lt;/li&gt;
&lt;li&gt;Teams increasingly separate:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;language/runtime cadence&lt;/strong&gt; (JDK upgrades)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;framework cadence&lt;/strong&gt; (Spring, Micronaut, Quarkus)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why it’s better
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Better throughput-per-core and latency consistency on modern workloads.&lt;/li&gt;
&lt;li&gt;Easier concurrency scaling with virtual threads for I/O-heavy services.&lt;/li&gt;
&lt;li&gt;Cleaner migration planning when platform teams enforce one baseline JDK per environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Trade-offs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;JDK upgrades surface hidden assumptions (reflection, unsafe libs, GC tuning folklore).&lt;/li&gt;
&lt;li&gt;Preview/incubator features are tempting but can create policy debates in regulated environments.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Adoption strategy (production-safe)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Move from “lift-and-pray” to &lt;strong&gt;benchmark-driven migration&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Enforce &lt;strong&gt;runtime parity&lt;/strong&gt; between CI and cluster images.&lt;/li&gt;
&lt;li&gt;Make rollback trivial: immutable image tags + GitOps revision pin.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Useful baseline command set:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# JVM + GC shape under realistic load&lt;/span&gt;
java &lt;span class="nt"&gt;-Xlog&lt;/span&gt;:gc&lt;span class="k"&gt;*&lt;/span&gt;:stdout:time &lt;span class="nt"&gt;-jar&lt;/span&gt; app.jar

&lt;span class="c"&gt;# JDK migration smoke check&lt;/span&gt;
jdeps &lt;span class="nt"&gt;--multi-release&lt;/span&gt; 21 &lt;span class="nt"&gt;--recursive&lt;/span&gt; app.jar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2) AI in production: model choice became a platform concern, not an app concern
&lt;/h2&gt;

&lt;p&gt;In many companies, AI features now sit inside Java APIs (classification, extraction, assistant workflows, anomaly triage). The biggest shift is operational: model routing, fallback, and cost controls are now platform-level primitives.&lt;/p&gt;

&lt;h3&gt;
  
  
  What changed
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Teams run &lt;strong&gt;multi-model strategies&lt;/strong&gt; (fast/small + accurate/expensive fallback).&lt;/li&gt;
&lt;li&gt;Inference is increasingly exposed behind internal gateways with quotas and observability.&lt;/li&gt;
&lt;li&gt;“Prompt quality” alone is no longer enough; SLOs and budget guardrails decide architecture.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why it’s better
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Better cost/performance by matching model size to request class.&lt;/li&gt;
&lt;li&gt;Easier governance (PII handling, rate limits, auditability) when centralized.&lt;/li&gt;
&lt;li&gt;Faster iteration when app teams consume a stable internal AI contract.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Trade-offs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;More infra complexity (gateways, retries, circuit breakers, prompt/version tracing).&lt;/li&gt;
&lt;li&gt;Evaluation debt: you need regression datasets, not just anecdotal testing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Practical Java pattern
&lt;/h3&gt;

&lt;p&gt;Keep application code model-agnostic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;AiClient&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;AiResult&lt;/span&gt; &lt;span class="nf"&gt;infer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AiRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then route by policy (latency tier, tenant, budget) outside business logic.&lt;/p&gt;

&lt;p&gt;And for reliability, treat AI calls like any other remote dependency:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;timeout budgets&lt;/li&gt;
&lt;li&gt;bulkheads&lt;/li&gt;
&lt;li&gt;fallback behavior&lt;/li&gt;
&lt;li&gt;semantic caching where safe&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3) Kubernetes: API drift and operations policy are now daily reality
&lt;/h2&gt;

&lt;p&gt;Kubernetes evolution is steady, and the operational impact is cumulative. Teams that delay upgrades too long pay the “API cliff” tax later.&lt;/p&gt;

&lt;h3&gt;
  
  
  What changed
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Deprecated APIs keep disappearing across releases.&lt;/li&gt;
&lt;li&gt;Security defaults and admission controls are tighter in modern clusters.&lt;/li&gt;
&lt;li&gt;Progressive delivery expectations grew: canary/blue-green is becoming standard for critical services.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why it’s better
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Better security posture by default.&lt;/li&gt;
&lt;li&gt;Fewer ambiguous deployment states.&lt;/li&gt;
&lt;li&gt;Better resilience when rollout policy is encoded instead of tribal.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Trade-offs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Manifest maintenance is continuous work, not one-off.&lt;/li&gt;
&lt;li&gt;Platform teams must own upgrade rehearsal and compatibility scanning.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Adoption strategy
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Run a scheduled &lt;strong&gt;API deprecation scan&lt;/strong&gt; in CI.&lt;/li&gt;
&lt;li&gt;Keep app manifests simple; push complexity to platform-level templates.&lt;/li&gt;
&lt;li&gt;Normalize probes/resources/securityContext defaults.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example deployment baseline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;orders-api&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
  &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RollingUpdate&lt;/span&gt;
    &lt;span class="na"&gt;rollingUpdate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;maxUnavailable&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
      &lt;span class="na"&gt;maxSurge&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;securityContext&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;runAsNonRoot&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghcr.io/acme/orders-api:1.12.0&lt;/span&gt;
          &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
          &lt;span class="na"&gt;readinessProbe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;httpGet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;/actuator/health/readiness&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;8080&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;livenessProbe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;httpGet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;/actuator/health/liveness&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;8080&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;250m"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;512Mi"&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1000m"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1Gi"&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4) CI/CD in 2026: from pipeline automation to delivery governance
&lt;/h2&gt;

&lt;p&gt;The old target was “green pipeline.” The new target is “trusted, reversible delivery.”&lt;/p&gt;

&lt;p&gt;That means three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build provenance/security signals&lt;/li&gt;
&lt;li&gt;Progressive deploy policy&lt;/li&gt;
&lt;li&gt;Fast rollback path&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  GitHub Actions example (build + scan + push)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build-and-push&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;
      &lt;span class="na"&gt;id-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
      &lt;span class="na"&gt;packages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-java@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;distribution&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;temurin&lt;/span&gt;
          &lt;span class="na"&gt;java-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;25'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./gradlew clean test bootJar&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build image&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;docker build -t ghcr.io/acme/orders-api:${{ github.sha }} .&lt;/span&gt;
          &lt;span class="s"&gt;docker push ghcr.io/acme/orders-api:${{ github.sha }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  GitLab CI example (test + image + manifest update)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;stages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;IMAGE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;registry.gitlab.com/acme/orders-api:$CI_COMMIT_SHA&lt;/span&gt;

&lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
  &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;eclipse-temurin:25&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./gradlew test&lt;/span&gt;

&lt;span class="na"&gt;build_image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
  &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker:27&lt;/span&gt;
  &lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;docker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;27-dind&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker build -t $IMAGE .&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker push $IMAGE&lt;/span&gt;

&lt;span class="na"&gt;deploy_gitops&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deploy&lt;/span&gt;
  &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;alpine:3.20&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;apk add --no-cache git yq&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/acme/platform-config.git&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cd platform-config/apps/orders-api/overlays/prod&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;yq -i '.images[0].newTag = env(CI_COMMIT_SHA)' kustomization.yaml&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;git config user.email "ci@acme.com"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;git config user.name "gitlab-ci"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;git commit -am "orders-api&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$CI_COMMIT_SHA"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;git push&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the key shift: &lt;strong&gt;application repo builds artifacts; config repo controls runtime state&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  5) GitOps with Argo CD: make rollback boring
&lt;/h2&gt;

&lt;p&gt;Argo CD works best when teams optimize for predictability, not cleverness.&lt;/p&gt;

&lt;h3&gt;
  
  
  Core production pattern
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;One app, one clear source of truth path&lt;/li&gt;
&lt;li&gt;Environment overlays (&lt;code&gt;dev/stage/prod&lt;/code&gt;) via Helm or Kustomize&lt;/li&gt;
&lt;li&gt;Sync policies explicit; auto-sync only where blast radius is understood&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example Argo CD Application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;argoproj.io/v1alpha1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Application&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;orders-api-prod&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;project&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;prod&lt;/span&gt;
  &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;repoURL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com/acme/platform-config.git&lt;/span&gt;
    &lt;span class="na"&gt;targetRevision&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/orders-api/overlays/prod&lt;/span&gt;
  &lt;span class="na"&gt;destination&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://kubernetes.default.svc&lt;/span&gt;
    &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;orders&lt;/span&gt;
  &lt;span class="na"&gt;syncPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;automated&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;prune&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;selfHeal&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;syncOptions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;CreateNamespace=true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Rollback strategy that actually works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Keep previous N image tags retained in registry.&lt;/li&gt;
&lt;li&gt;Revert config commit (not kubectl patch in prod).&lt;/li&gt;
&lt;li&gt;Measure rollback MTTR as a platform KPI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If rollback is manual and stressful, your delivery system is unfinished.&lt;/p&gt;




&lt;h2&gt;
  
  
  6) A realistic 90-day adoption roadmap
&lt;/h2&gt;

&lt;p&gt;If your current baseline is Java 17/21 + Kubernetes + ad-hoc CI, here is a pragmatic rollout:&lt;/p&gt;

&lt;h3&gt;
  
  
  Days 1–30: Stabilize the foundation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Inventory JDK/runtime versions and unsupported dependencies.&lt;/li&gt;
&lt;li&gt;Standardize base container image and JVM flags.&lt;/li&gt;
&lt;li&gt;Add deployment health checks and resource defaults.&lt;/li&gt;
&lt;li&gt;Introduce config repo for at least one service.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Days 31–60: Secure and govern delivery
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add image scanning + dependency checks in CI.&lt;/li&gt;
&lt;li&gt;Enforce branch protections and required pipeline gates.&lt;/li&gt;
&lt;li&gt;Add Argo CD for one production service with clear rollback drill.&lt;/li&gt;
&lt;li&gt;Define AI request classes and model routing policy.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Days 61–90: Optimize for speed and reliability
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Migrate a high-traffic Java service to latest target JDK.&lt;/li&gt;
&lt;li&gt;Add canary rollout policy for critical services.&lt;/li&gt;
&lt;li&gt;Instrument end-to-end latency (API + model + DB) with SLO dashboards.&lt;/li&gt;
&lt;li&gt;Track DORA + rollback MTTR + AI cost/request in one operational view.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final take
&lt;/h2&gt;

&lt;p&gt;The winning pattern in 2026 is not “adopt every new thing fast.”&lt;/p&gt;

&lt;p&gt;It is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Upgrade deliberately&lt;/strong&gt; (Java + Kubernetes)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operationalize AI&lt;/strong&gt; (routing, reliability, cost controls)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treat CI/CD as governance&lt;/strong&gt; (not just automation)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use GitOps to make rollback routine&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your team can answer, at any moment, &lt;em&gt;what changed, why it changed, and how to revert safely&lt;/em&gt;, you are ahead of most organizations already.&lt;/p&gt;

&lt;p&gt;That’s what mature platform engineering looks like today.&lt;/p&gt;

</description>
      <category>java</category>
      <category>kubernetes</category>
      <category>devops</category>
      <category>ai</category>
    </item>
    <item>
      <title>Replacing org.n52 JtsModule for Jackson 3: Introducing io.github.aytronnfr.jackson.jts.JtsModule</title>
      <dc:creator>Titouan Despierres</dc:creator>
      <pubDate>Fri, 20 Feb 2026 15:59:20 +0000</pubDate>
      <link>https://dev.to/aytronn/replacing-orgn52-jtsmodule-for-jackson-3-introducing-iogithubaytronnfrjacksonjtsjtsmodule-1gjp</link>
      <guid>https://dev.to/aytronn/replacing-orgn52-jtsmodule-for-jackson-3-introducing-iogithubaytronnfrjacksonjtsjtsmodule-1gjp</guid>
      <description>&lt;h1&gt;
  
  
  Replacing &lt;code&gt;org.n52.jackson.datatype.jts.JtsModule&lt;/code&gt; for Jackson 3: Introducing &lt;code&gt;io.github.aytronnfr.jackson.jts.JtsModule&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;If you are migrating to Spring Boot 4 and Jackson 3, you have probably hit this problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;your geospatial JSON stack still depends on Jackson 2-era modules,&lt;/li&gt;
&lt;li&gt;but your app now runs on &lt;code&gt;tools.jackson.*&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hit the same wall and built a replacement module:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;old&lt;/strong&gt;: &lt;code&gt;org.n52.jackson.datatype.jts.JtsModule&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;new&lt;/strong&gt;: &lt;code&gt;io.github.aytronnfr.jackson.jts.JtsModule&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Repository: &lt;a href="https://github.com/aytronnFR/jts-jackson3-module" rel="noopener noreferrer"&gt;https://github.com/aytronnFR/jts-jackson3-module&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;jts-jackson3-module&lt;/code&gt; provides GeoJSON serialization/deserialization for JTS on &lt;strong&gt;Jackson 3&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;It is designed for &lt;strong&gt;Spring Boot 4.x&lt;/strong&gt; projects using &lt;code&gt;tools.jackson.*&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It includes round-trip and compatibility tests to reduce migration risk.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why this module exists
&lt;/h2&gt;

&lt;p&gt;Spring Boot 4 moves to Jackson 3. That means many older JSON modules built around Jackson 2 package names no longer fit cleanly.&lt;/p&gt;

&lt;p&gt;For JTS geometries, this can block migration or force ugly temporary workarounds.&lt;/p&gt;

&lt;p&gt;This module is a drop-in migration path for teams that need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;clean support for &lt;code&gt;org.locationtech.jts&lt;/code&gt; geometries,&lt;/li&gt;
&lt;li&gt;GeoJSON read/write behavior,&lt;/li&gt;
&lt;li&gt;modern build/publish workflow (GitHub Packages + Maven Central).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Compatibility targets
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;jts-jackson3-module&lt;/code&gt; is built for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spring Boot 4.x&lt;/li&gt;
&lt;li&gt;Jackson 3 (&lt;code&gt;tools.jackson.*&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;JTS (&lt;code&gt;org.locationtech.jts&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Dependency
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"io.github.aytronnfr:jts-jackson3-module:0.1.0"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Basic usage
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.github.aytronnfr.jackson.jts.JtsModule&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tools.jackson.databind.json.JsonMapper&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.locationtech.jts.geom.GeometryFactory&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.locationtech.jts.geom.PrecisionModel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nd"&gt;@Configuration&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JsonConfig&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;@Bean&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;GeometryFactory&lt;/span&gt; &lt;span class="nf"&gt;geometryFactory&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;GeometryFactory&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PrecisionModel&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;4326&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;configJsonMapper&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;GeometryFactory&lt;/span&gt; &lt;span class="n"&gt;geometryFactory&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Builder&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 1) Modules&lt;/span&gt;
    &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addModule&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;JtsModule&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;geometryFactory&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s enough to start serializing/deserializing JTS geometries in a Jackson 3 stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced usage: include bbox for selected geometry types
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.github.aytronnfr.jackson.jts.GeometryType&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.github.aytronnfr.jackson.jts.IncludeBoundingBox&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.github.aytronnfr.jackson.jts.JtsModule&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;JtsModule&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IncludeBoundingBox&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;forTypes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;GeometryType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;POINT&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This lets you control output precision and bounding-box behavior for targeted geometry classes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migration notes from &lt;code&gt;org.n52...&lt;/code&gt; module
&lt;/h2&gt;

&lt;p&gt;When migrating, I recommend this order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Replace dependency with &lt;code&gt;io.github.aytronnfr:jts-jackson3-module&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Register &lt;code&gt;new JtsModule()&lt;/code&gt; in your Jackson 3 &lt;code&gt;JsonMapper&lt;/code&gt; config.&lt;/li&gt;
&lt;li&gt;Run contract tests against existing API payload fixtures.&lt;/li&gt;
&lt;li&gt;Validate edge cases: precision, bbox output, null geometry handling.&lt;/li&gt;
&lt;li&gt;Roll out with canary if geospatial payloads are customer-facing.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Testing strategy used in the project
&lt;/h2&gt;

&lt;p&gt;The repo includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;round-trip tests&lt;/strong&gt; for Jackson 3 behavior,&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;compat tests&lt;/strong&gt; against legacy &lt;code&gt;org.n52.jackson:jackson-datatype-jts:2.0.0&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;shared fixtures for deterministic comparisons.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is important because geospatial JSON regressions are often subtle (ordering, precision, bbox shape) and can break downstream consumers silently.&lt;/p&gt;

&lt;h2&gt;
  
  
  CI/CD and publishing
&lt;/h2&gt;

&lt;p&gt;The project includes GitHub Actions for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CI on push/PR,&lt;/li&gt;
&lt;li&gt;publish on version tags,&lt;/li&gt;
&lt;li&gt;manual release flow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Publishing is wired for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub Packages&lt;/li&gt;
&lt;li&gt;Maven Central&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Practical impact for Boot 4 teams
&lt;/h2&gt;

&lt;p&gt;In real migrations, this removes a key blocker: staying with old module assumptions while the rest of your app has already moved to Jackson 3.&lt;/p&gt;

&lt;p&gt;You keep your geospatial payload capability without freezing your platform upgrade.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next
&lt;/h2&gt;

&lt;p&gt;The roadmap I’m focusing on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;expand compatibility fixtures,&lt;/li&gt;
&lt;li&gt;benchmark serialization overhead on larger geometry sets,&lt;/li&gt;
&lt;li&gt;document migration recipes for common Spring Boot setups.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re migrating a GIS-heavy API to Boot 4, feedback and issue reports are very welcome.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/aytronnFR/jts-jackson3-module" rel="noopener noreferrer"&gt;https://github.com/aytronnFR/jts-jackson3-module&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>jackson</category>
      <category>geojson</category>
    </item>
    <item>
      <title>Spring Boot 4.0 Migration Guide for Production Teams: What Actually Breaks and How to Upgrade Safely</title>
      <dc:creator>Titouan Despierres</dc:creator>
      <pubDate>Fri, 20 Feb 2026 12:54:50 +0000</pubDate>
      <link>https://dev.to/aytronn/spring-boot-40-migration-guide-for-production-teams-what-actually-breaks-and-how-to-upgrade-safely-22me</link>
      <guid>https://dev.to/aytronn/spring-boot-40-migration-guide-for-production-teams-what-actually-breaks-and-how-to-upgrade-safely-22me</guid>
      <description>&lt;h1&gt;
  
  
  Spring Boot 4.0 Migration Guide for Production Teams: What Actually Breaks and How to Upgrade Safely
&lt;/h1&gt;

&lt;p&gt;Spring Boot 4.0 is not a routine version bump. For most Java teams, it is a platform migration touching Java baseline, Jakarta alignment, dependency graph, packaging behavior, test setup, and especially JSON handling with Jackson 3.&lt;/p&gt;

&lt;p&gt;This guide summarizes the official migration notes into a practical, production-focused playbook.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Upgrade to the latest &lt;strong&gt;3.5.x&lt;/strong&gt; first, remove deprecations, then move to 4.0.&lt;/li&gt;
&lt;li&gt;The biggest migration risks are &lt;strong&gt;module/starter changes&lt;/strong&gt; and &lt;strong&gt;Jackson 3 behavior shifts&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Use a staged rollout: stabilize with compatibility options, then converge to native Boot 4 patterns.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why this migration is bigger than usual
&lt;/h2&gt;

&lt;p&gt;Spring Boot 4.0 upgrades major foundations at once:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java baseline: &lt;strong&gt;17+&lt;/strong&gt; (latest LTS recommended)&lt;/li&gt;
&lt;li&gt;Servlet baseline: &lt;strong&gt;6.1&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Jakarta EE: &lt;strong&gt;11&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Spring Framework: &lt;strong&gt;7.x&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Preferred JSON engine: &lt;strong&gt;Jackson 3&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That means many apps compile but still fail at runtime (serialization contracts, missing transitive dependencies, test infra drift, startup assumptions).&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 0: Before touching Boot 4
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1) Move to latest Boot 3.5.x
&lt;/h3&gt;

&lt;p&gt;Do this first so you are already on the newest dependency line and can clean warnings progressively.&lt;/p&gt;

&lt;h3&gt;
  
  
  2) Remove 3.x deprecations
&lt;/h3&gt;

&lt;p&gt;Anything deprecated in Boot 3.x is a removal candidate in 4.0.&lt;/p&gt;

&lt;h3&gt;
  
  
  3) Audit external BOMs and managed libs
&lt;/h3&gt;

&lt;p&gt;If you pin versions outside Boot management (for example Spring Cloud), validate Boot 4 compatibility before upgrading.&lt;/p&gt;

&lt;h3&gt;
  
  
  4) Re-check environment requirements
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Java 17+&lt;/li&gt;
&lt;li&gt;Kotlin 2.2+ (if used)&lt;/li&gt;
&lt;li&gt;GraalVM 25+ for native-image&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Features removed in Boot 4 you must account for
&lt;/h2&gt;

&lt;p&gt;From the migration guide, notable removals include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Undertow support dropped&lt;/strong&gt; (Servlet 6.1 baseline incompatibility)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pulsar reactive auto-configuration removed&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Embedded launch scripts for fully executable jars removed&lt;/li&gt;
&lt;li&gt;Spock integration removed (Groovy 5 gap)&lt;/li&gt;
&lt;li&gt;Direct Boot support removed for Spring Session Hazelcast/MongoDB integrations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your runtime or packaging relies on these features, plan alternatives before switching versions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The biggest structural change: modularization
&lt;/h2&gt;

&lt;p&gt;Boot 4 introduces smaller focused modules and a more consistent starter model.&lt;/p&gt;

&lt;h3&gt;
  
  
  What changes in practice
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;More technologies now have dedicated starters.&lt;/li&gt;
&lt;li&gt;Test infra is also modularized with companion test starters.&lt;/li&gt;
&lt;li&gt;If your app relied on implicit transitive deps, you may now miss required pieces.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Typical example
&lt;/h3&gt;

&lt;p&gt;If you used Flyway/Liquibase only via third-party dependency before, Boot 4 expects explicit Boot starter usage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;spring-boot-starter-flyway&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;spring-boot-starter-liquibase&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Test side impact
&lt;/h3&gt;

&lt;p&gt;You should depend on technology-specific test starters, not just one global test starter.&lt;/p&gt;

&lt;p&gt;For example, security test behavior now expects proper security test starter alignment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Transition path: classic starters
&lt;/h2&gt;

&lt;p&gt;For teams upgrading a large legacy codebase, Boot 4 provides a temporary bridge:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;spring-boot-starter-classic&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;spring-boot-starter-test-classic&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use this to restore broad classpath coverage, fix imports/configs, then progressively move to focused starters.&lt;/p&gt;

&lt;p&gt;Treat this as transitional, not the end state.&lt;/p&gt;

&lt;h2&gt;
  
  
  Jackson 3 migration: the highest-risk area
&lt;/h2&gt;

&lt;p&gt;Boot 4 prefers Jackson 3 and introduces major ecosystem changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key changes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Group/package migration from &lt;code&gt;com.fasterxml.jackson&lt;/code&gt; to &lt;code&gt;tools.jackson&lt;/code&gt; (with exceptions)&lt;/li&gt;
&lt;li&gt;Boot integration class renames for consistency&lt;/li&gt;
&lt;li&gt;Property namespace changes for JSON-specific read/write settings&lt;/li&gt;
&lt;li&gt;Automatic registration of all classpath Jackson modules by default&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Immediate risks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;API payload differences (date/time formatting, null/default handling)&lt;/li&gt;
&lt;li&gt;stricter or different deserialization outcomes&lt;/li&gt;
&lt;li&gt;polymorphic payload regressions&lt;/li&gt;
&lt;li&gt;subtle contract breakage across clients&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Useful compatibility controls
&lt;/h3&gt;

&lt;p&gt;Boot 4 adds transitional options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;spring.jackson.use-jackson2-defaults=true&lt;/code&gt; (closer behavior to Boot 3/Jackson 2 defaults)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;spring-boot-jackson2&lt;/code&gt; module as temporary stop-gap&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use these as migration aids, not long-term architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other migration changes teams miss
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;JSpecify nullability annotations can affect Kotlin/null-check tooling&lt;/li&gt;
&lt;li&gt;Logback default charset behavior now aligned with UTF-8 expectations&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;BootstrapRegistry&lt;/code&gt; / &lt;code&gt;EnvironmentPostProcessor&lt;/code&gt; package moves can break deep integrations&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PropertyMapper&lt;/code&gt; no longer maps null source values by default (use &lt;code&gt;always()&lt;/code&gt; when needed)&lt;/li&gt;
&lt;li&gt;DevTools LiveReload now disabled by default&lt;/li&gt;
&lt;li&gt;Optional Maven dependencies no longer included by default in uber jars&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Recommended production migration strategy
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Phase 1 — Stabilize
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Upgrade to latest 3.5.x&lt;/li&gt;
&lt;li&gt;Remove deprecations&lt;/li&gt;
&lt;li&gt;Upgrade to Boot 4 with classic starters&lt;/li&gt;
&lt;li&gt;Ensure app starts and core flows run&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Phase 2 — Correctness
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Add contract tests for JSON payloads&lt;/li&gt;
&lt;li&gt;Verify Jackson behavior against real fixtures&lt;/li&gt;
&lt;li&gt;Fix dependency graph explicitly (main + test)&lt;/li&gt;
&lt;li&gt;Validate startup/runtime with production-like config&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Phase 3 — Convergence
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Replace classic starters with focused starters&lt;/li&gt;
&lt;li&gt;Remove compatibility flags one by one&lt;/li&gt;
&lt;li&gt;Re-check observability and actuator behavior&lt;/li&gt;
&lt;li&gt;Final cleanup and docs update&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  CI/CD checks you should add before rollout
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Dependency diff gate (3.5 vs 4.0)&lt;/li&gt;
&lt;li&gt;Contract test stage for API payload compatibility&lt;/li&gt;
&lt;li&gt;Integration tests with representative fixtures&lt;/li&gt;
&lt;li&gt;Canary rollout + error budget guardrails&lt;/li&gt;
&lt;li&gt;Fast rollback trigger on error spike&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Practical checklist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Latest 3.5.x in production first&lt;/li&gt;
&lt;li&gt;[ ] No known 3.x deprecations in code paths&lt;/li&gt;
&lt;li&gt;[ ] Environment meets Java/Jakarta/Servlet requirements&lt;/li&gt;
&lt;li&gt;[ ] Removed features audited (Undertow, etc.)&lt;/li&gt;
&lt;li&gt;[ ] Jackson migration strategy selected (native vs transitional)&lt;/li&gt;
&lt;li&gt;[ ] Starter and test-starter dependencies reviewed&lt;/li&gt;
&lt;li&gt;[ ] Contract/integration tests green&lt;/li&gt;
&lt;li&gt;[ ] Canary + rollback plan validated&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final takeaway
&lt;/h2&gt;

&lt;p&gt;Spring Boot 4.0 gives a cleaner long-term model, but migration quality depends on discipline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;explicit dependencies,&lt;/li&gt;
&lt;li&gt;explicit JSON behavior,&lt;/li&gt;
&lt;li&gt;explicit rollout strategy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you treat it as a platform migration instead of a “version bump”, the upgrade is predictable and safe.&lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>jackson</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
