Currently viewing the human version
Switch to AI version

Why Zuul is Dead

Spring Cloud Netflix Zuul was deprecated in 2021 and hasn't been updated since. No security patches, no bug fixes, no Spring Boot 3 support.

Spring Cloud Gateway Architecture

Spring Boot 3 Breaks Everything

You can't use Spring Cloud Zuul with Spring Boot 3. The dependencies don't align, and you'll get UnsatisfiedDependencyException errors that make no sense. I spent 6 hours debugging this before realizing it's just not supported.

The workarounds on Stack Overflow involve excluding Jersey and manually aligning Spring Cloud versions, but that's just delaying the inevitable.

Two Different Zuuls (This Confuses Everyone)

There are two projects called Zuul:

  1. Netflix Zuul - The core gateway (still maintained, v3.2.0 released September 2025)
  2. Spring Cloud Netflix Zuul - The Spring wrapper (dead since 2021)

Netflix's core Zuul project is fine. It's the Spring Cloud integration that's dead. Spring moved to Spring Cloud Gateway for reactive support.

What Actually Breaks During Migration

Filters don't translate: Zuul filters use RequestContext which doesn't exist in Gateway. Every custom filter needs rewriting. I had 12 filters and rewrote all of them.

Load balancer config changes: Ribbon configuration from Zuul doesn't work in Gateway. You'll need to switch to Spring Cloud LoadBalancer, and the YAML syntax is different.

Error handling is different: Gateway's error handling uses reactive streams. If you don't understand Mono/Flux, debugging becomes painful. Our auth filter silently failed for 3 weeks because the error handling works differently.

Route configuration format: Gateway uses predicate-based routing instead of Zuul's pattern matching. Everything needs converting.

The Real Migration Timeline

Plan at least 2-3 months. Teams always underestimate this migration. The code changes are 30% of the work - testing and finding edge cases is the other 70%.

We had staging working in 2 weeks. Production took another 6 weeks because reactive Gateway handles load differently and our health checks broke.

Migration Options

Feature

Spring Cloud Gateway

Netflix Zuul 2 (Direct)

Spring Cloud Gateway MVC

Migration Effort

Depends on how fucked your current setup is

Complete rewrite

Easiest if you have simple filters

Spring Integration

✅ Native Spring Cloud

❌ You're on your own

✅ Native Spring MVC

Programming Model

Reactive (WebFlux)

Async/Netty

Blocking (MVC)

Learning Curve

Steep if you don't know reactive

Brutal (Netty internals)

Low (familiar MVC)

Performance

Fast under load

Fastest

Good enough for most cases

Filter Migration

Complete rewrite

Complete rewrite

Similar API to Zuul

What Breaks

RequestContext, error handling

Everything

Less stuff

Documentation

Good but assumes reactive knowledge

Sparse, Netflix-focused

New but improving

Real Blocker

Reactive learning curve

No Spring integration

Missing some Gateway features

How to Actually Migrate (Without Breaking Production)

I learned this the hard way: the migration isn't just swapping dependencies. Your filters won't work, your config needs rewriting, and you'll discover Zuul-specific assumptions buried in your code.

Step 1: Inventory Your Zuul Mess

Spring Boot Gateway Migration

First, document what you have:

## Your current zuul configuration
zuul:
  routes:
    user-service:
      path: /users/**
      serviceId: user-service
    order-service:
      path: /orders/**
      serviceId: order-service

user-service:
  ribbon:
    listOfServers: http://user-service:8080

Catalog every custom filter (this will take longer than you think):

  • Filter type (PRE_TYPE, POST_TYPE, ROUTE_TYPE, ERROR_TYPE)
  • Filter order (execution sequence matters)
  • Dependencies on RequestContext or external services

I spent 3 days cataloging filters on my last migration because nobody documented the custom authentication filter that was buried in a utility jar. Don't make that mistake.

Step 2: Pick Your Poison (Gateway MVC vs Reactive)

Gateway MVC is easier if you want to minimize learning curve:

@Configuration
public class ServiceRouter {

    @Bean
    public RouterFunction<ServerResponse> userServiceRouter() {
        return route()
            .route(path(\"/users/**\"), http())
            .filter(lb(\"user-service\"))
            .before(authenticationFilter())
            .after(loggingFilter())
            .build();
    }
}

Reactive Gateway if you don't mind learning Mono/Flux:

@Configuration
public class GatewayConfig {

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
            .route(\"user-service\", r -> r.path(\"/users/**\")
                .filters(f -> f.stripPrefix(1))
                .uri(\"lb://user-service\"))
            .build();
    }
}

Start with MVC unless you enjoy pain. You can always migrate to reactive later, but reactive has a learning curve that will slow down your migration and make you question your life choices.

Step 3: Rewrite Your Filters (Pain Incoming)

This is where you'll lose sleep. Your Zuul filters use RequestContext which doesn't exist in Gateway. Here's what a typical filter migration looks like:

Your existing Zuul filter:

@Component
public class AuthenticationFilter extends ZuulFilter {

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();

        String token = request.getHeader(\"Authorization\");
        if (!validateToken(token)) {
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            return null;
        }
        return null;
    }
}

Gateway MVC equivalent (easier):

public static Function<ServerRequest, ServerRequest> authenticationFilter() {
    return request -> {
        String token = request.headers().firstHeader(\"Authorization\");
        if (!validateToken(token)) {
            throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
        }
        return request;
    };
}

Reactive Gateway equivalent (harder):

@Component
public class AuthenticationGatewayFilter implements GatewayFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst(\"Authorization\");

        if (!validateToken(token)) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }

        return chain.filter(exchange);
    }
}

Reality check: I spent 2 weeks rewriting 8 filters on my last migration, and that was with documentation. Yours will probably take longer because there's always some undocumented bullshit filter buried in a utility jar that nobody remembers writing.

Step 4: Test Without Breaking Production

Run both gateways in parallel (trust me on this):

## Traffic splitting with headers
spring:
  cloud:
    gateway:
      routes:
        - id: user-service-test
          uri: lb://user-service
          predicates:
            - Path=/users/**
            - Header=X-Test-Migration, true

Start with 1% traffic using header routing, monitor like hell, then increase gradually. I've seen teams skip this step and take down production for 2 hours when their authentication filter broke.

Step 5: The Actual Cutover

What will break (from experience):

  • Request/response transformation: Gateway handles this differently than Zuul
  • Error propagation: Exceptions don't bubble up the same way
  • Timeouts: Gateway MVC doesn't support per-route timeouts yet
  • Load balancer config: Ribbon settings don't translate directly

Monitoring you actually need:

  • Response time percentiles (watch for p99 spikes)
  • Error rates by service (authentication failures spike during cutover)
  • Memory usage (reactive can use more heap initially)

Response times spike during JVM warm-up, then settle at better performance than Zuul if you're lucky.

Gotchas That Will Bite You

RequestContext doesn't exist: Use exchange attributes instead. They work differently and you'll spend days figuring out the new APIs.

Filter ordering is explicit: Gateway requires explicit ordering vs. Zuul's implicit filter registration order. This will break in subtle ways.

Reactive error handling: If you go reactive, custom error handlers are needed for proper exception propagation. The default error handling swallows exceptions.

Memory usage changes: Reactive Gateway initially uses more heap during startup, then stabilizes. Monitor this.

Health checks might fail: Gateway expects different endpoints than Zuul. Your monitoring will think services are down when they're not.

Load balancer retries: Spring Cloud LoadBalancer has different retry semantics than Ribbon. Your fail-fast assumptions might be wrong.

Timeline reality check: Plan 2-3 months minimum. Every migration takes longer than expected because there's always some edge case that breaks at 3am in production.

Migration Questions Every Team Asks (And Honest Answers)

Q

How urgent is this migration really?

A

Pretty urgent. Spring Cloud Netflix Zuul hasn't been updated since November 2021. No security patches, no Spring Boot 3 support. Your security team will flag this during audits, and Spring Boot 3 integration throws UnsatisfiedDependencyException errors that get progressively harder to work around.

Q

Can I just use the actual Netflix Zuul and avoid this migration hell?

A

You could, but you'll hate yourself. Netflix Zuul 2 is actively maintained (v3.2.0 released September 2025), but you lose all Spring Cloud integration. You'll need to manually wire up service discovery, load balancing, and configuration. Even Netflix moved to Spring Cloud Gateway internally.

Q

What's the difference between Spring Cloud Gateway and Spring Cloud Gateway MVC?

A

Gateway MVC is designed for easier migration from Zuul. Gateway (reactive) uses WebFlux and reactive programming, while Gateway MVC uses familiar blocking MVC patterns. Teams report Gateway MVC takes 1-3 weeks vs. 4-7 weeks for reactive Gateway. Gateway MVC was released in November 2023 specifically to ease Zuul migrations.

Q

Do I really need to rewrite all my Zuul filters?

A

Yes, all of them. Every fucking one. Zuul filters use RequestContext and servlet-based APIs, while Gateway uses reactive streams or functional interfaces. The concepts translate (pre/post filters become before/after), but the code is completely different. This is going to suck and there's no way around it.

Q

How do I handle the reactive programming learning curve?

A

Start with Gateway MVC if reactive is intimidating. Gateway MVC uses familiar Function<ServerRequest, ServerRequest> patterns similar to Zuul. If you choose reactive Gateway, expect your team to need 2-4 weeks to become productive with Mono/Flux patterns.

Q

Can I run both gateways during migration?

A

Yes, and you should. Deploy both gateways and use traffic splitting for gradual rollout. Start with 1% traffic to Gateway, monitor metrics, increase gradually. Most teams use header-based routing (X-Test-Migration: true) for controlled testing. This parallel approach minimizes risk but requires careful coordination.

Q

What about per-service timeout configuration?

A

Gateway MVC doesn't support it yet. Zuul with Ribbon allowed per-service read timeouts (user-service.ribbon.ReadTimeout: 30000). Gateway MVC only supports global timeouts currently. There's an open GitHub issue for this feature. Plan workarounds or accept global timeouts for now.

Q

Seriously, how long is this migration actually going to take?

A

Longer than you think. Gateway MVC takes 3-4 weeks if you're lucky, reactive Gateway takes a month or more because reactive programming is a mindfuck, and direct Zuul 2 takes 2-3 months because Netflix doesn't provide migration tools. Double whatever estimate you give management.

Q

Will performance improve after migration?

A

Usually yes, but not immediately. Teams report similar memory/CPU usage but better throughput under load. Expect initial performance dips during JVM warm-up, then stabilization at better performance than Zuul. Reactive Gateway handles high-concurrency scenarios better due to non-blocking I/O.

Q

Should I migrate to Kubernetes-native gateways instead?

A

Only if you're already fully committed to Kubernetes. Ambassador, Kong, or service mesh gateways work well in K8s environments, but they require learning new tools and losing Spring integration benefits. If you're heavily invested in Spring ecosystem, Gateway MVC provides better integration and familiar patterns.

Q

My team is swamped - can we just delay this migration?

A

No. Make time or accept that you're running unpatched software in production. Every month you delay makes this worse. Your choices are: hire contractors to do the migration, stop feature development for a month, or explain to your security team why you're running 4-year-old gateway software with known vulnerabilities. Pick your poison.

Q

Can I use this as an opportunity to move away from Spring Cloud entirely?

A

Yes, but that's a much bigger project. If you're questioning the entire Spring Cloud approach, consider Kong, Ambassador, or cloud-native gateways. However, that's a 6-12 month architectural change vs. a 4-8 week migration. Don't conflate gateway migration with architectural overhaul unless you have strong business drivers.

Q

How do I convince management this migration is necessary?

A

Frame it as security and compliance, not technical debt. Emphasize: unpatched security vulnerabilities in your API gateway, compliance audit failures for outdated dependencies, and increasing maintenance costs for workarounds. Show migration timeline vs. business risk of staying on deprecated software.

Q

What happens if I just... don't migrate?

A

Your gateway becomes increasingly brittle. Spring Boot 3.x integration requires more workarounds over time. Security vulnerabilities accumulate. New team members expect modern, maintained tools. Eventually, you'll be forced to migrate under pressure with less planning time. Better to migrate proactively than reactively under incident pressure.

Related Tools & Recommendations

integration
Recommended

Stop Fighting Your CI/CD Tools - Make Them Work Together

When Jenkins, GitHub Actions, and GitLab CI All Live in Your Company

GitHub Actions
/integration/github-actions-jenkins-gitlab-ci/hybrid-multi-platform-orchestration
100%
alternatives
Recommended

GitHub Actions is Fucking Slow: Alternatives That Actually Work

competes with GitHub Actions

GitHub Actions
/alternatives/github-actions/performance-optimized-alternatives
92%
tool
Recommended

GitLab CI/CD - The Platform That Does Everything (Usually)

CI/CD, security scanning, and project management in one place - when it works, it's great

GitLab CI/CD
/tool/gitlab-ci-cd/overview
67%
compare
Recommended

I Tested 4 AI Coding Tools So You Don't Have To

Here's what actually works and what broke my workflow

Cursor
/compare/cursor/github-copilot/claude-code/windsurf/codeium/comprehensive-ai-coding-assistant-comparison
64%
tool
Recommended

GitHub CLI Enterprise Chaos - When Your Deploy Script Becomes Your Boss

integrates with GitHub CLI

GitHub CLI
/brainrot:tool/github-cli/enterprise-automation
64%
integration
Recommended

Jenkins + Docker + Kubernetes: How to Deploy Without Breaking Production (Usually)

The Real Guide to CI/CD That Actually Works

Jenkins
/integration/jenkins-docker-kubernetes/enterprise-ci-cd-pipeline
42%
integration
Recommended

GitHub Actions + Jenkins Security Integration

When Security Wants Scans But Your Pipeline Lives in Jenkins Hell

GitHub Actions
/integration/github-actions-jenkins-security-scanning/devsecops-pipeline-integration
42%
integration
Recommended

Stop manually configuring servers like it's 2005

Here's how Terraform, Packer, and Ansible work together to automate your entire infrastructure stack without the usual headaches

Terraform
/integration/terraform-ansible-packer/infrastructure-automation-pipeline
42%
tool
Recommended

Red Hat Ansible Automation Platform - Ansible with Enterprise Support That Doesn't Suck

If you're managing infrastructure with Ansible and tired of writing wrapper scripts around ansible-playbook commands, this is Red Hat's commercial solution with

Red Hat Ansible Automation Platform
/tool/red-hat-ansible-automation-platform/overview
42%
tool
Recommended

Ansible - Push Config Without Agents Breaking at 2AM

Stop babysitting daemons and just use SSH like a normal person

Ansible
/tool/ansible/overview
42%
tool
Recommended

GitHub Actions Security Hardening - Prevent Supply Chain Attacks

competes with GitHub Actions

GitHub Actions
/tool/github-actions/security-hardening
38%
tool
Recommended

GitHub Actions Cost Optimization - When Your CI Bill Is Higher Than Your Rent

competes with GitHub Actions

GitHub Actions
/brainrot:tool/github-actions/performance-optimization
38%
pricing
Recommended

GitHub Enterprise vs GitLab Ultimate - Total Cost Analysis 2025

The 2025 pricing reality that changed everything - complete breakdown and real costs

GitHub Enterprise
/pricing/github-enterprise-vs-gitlab-cost-comparison/total-cost-analysis
38%
howto
Recommended

Stop Breaking FastAPI in Production - Kubernetes Reality Check

What happens when your single Docker container can't handle real traffic and you need actual uptime

FastAPI
/howto/fastapi-kubernetes-deployment/production-kubernetes-deployment
38%
integration
Recommended

Temporal + Kubernetes + Redis: The Only Microservices Stack That Doesn't Hate You

Stop debugging distributed transactions at 3am like some kind of digital masochist

Temporal
/integration/temporal-kubernetes-redis-microservices/microservices-communication-architecture
38%
howto
Recommended

Your Kubernetes Cluster is Probably Fucked

Zero Trust implementation for when you get tired of being owned

Kubernetes
/howto/implement-zero-trust-kubernetes/kubernetes-zero-trust-implementation
38%
tool
Recommended

CircleCI - Fast CI/CD That Actually Works

alternative to CircleCI

CircleCI
/tool/circleci/overview
34%
tool
Recommended

Travis CI - The CI Service That Used to Be Great (Before GitHub Actions)

Travis CI was the CI service that saved us from Jenkins hell in 2011, but GitHub Actions basically killed it

Travis CI
/tool/travis-ci/overview
34%
tool
Recommended

Azure Pipelines - CI/CD That Actually Handles Windows

alternative to Azure Pipelines

Azure Pipelines
/tool/azure-pipelines/overview
30%
tool
Recommended

Fix Azure Pipelines YAML Errors That Break Builds

When your YAML pipeline keeps failing with cryptic errors, here's how to actually debug it

Azure Pipelines
/tool/azure-pipelines/yaml-debugging-guide
30%

Recommendations combine user behavior, content similarity, research intelligence, and SEO optimization