Gateway reativo vs MVC — as duas variantes

TL;DR

O Spring Cloud Gateway hoje tem duas variantes vivas do servidor — você escolhe uma na hora de declarar o starter:

  • Reativaspring-cloud-starter-gateway-server-webflux. Roda sobre WebFlux/Netty, modelo não-bloqueante. É o gateway original, o que a maioria dos tutoriais ainda assume.
  • MVCspring-cloud-starter-gateway-server-webmvc. Roda sobre o stack servlet (bloqueante). É a variante mais nova, para quem não quer carregar o modelo reativo só por causa do gateway.
  • Os dois starters foram renomeados no trem 2025.x: o reativo era spring-cloud-starter-gateway e o MVC era spring-cloud-starter-gateway-mvc. Usar o nome antigo é a armadilha número um. Regra de bolso: time já reativo → WebFlux; time servlet/MVC sem fluência reativa → WebMVC. O modelo reativo em si (Netty, backpressure) é assunto do Galho 11 — aqui você só escolhe a variante.

O que é

O API Gateway é a porta única na frente dos seus serviços: roteia, filtra, casa predicates. O Spring Cloud Gateway é a implementação idiomática desse papel no ecossistema Spring.

O que muitos não percebem é que “Spring Cloud Gateway” não é mais um produto só. Existem duas variantes do servidor, que fazem o mesmo trabalho de gateway, mas assentam sobre stacks web diferentes:

  1. Gateway Server WebFlux — o gateway reativo, sobre o stack WebFlux/Netty, não-bloqueante. É a encarnação histórica: por anos, “Spring Cloud Gateway” era isto, e ponto.
  2. Gateway Server WebMVC — o gateway sobre o stack Spring MVC (servlet), bloqueante. Nasceu para um público específico: quem tem uma aplicação MVC tradicional e não quer introduzir o runtime reativo só para ter um gateway.

Feynman: duas portarias para o mesmo prédio

Imagine o gateway como a portaria de um condomínio. As duas variantes fazem o mesmo serviço — conferem quem entra, encaminham para o bloco certo. A diferença é o regime de trabalho do porteiro. Na variante reativa (WebFlux), um único porteiro atende muitas pessoas ao mesmo tempo, sem ficar parado esperando o elevador de cada uma chegar. Na variante MVC (servlet), cada atendimento ocupa um porteiro do início ao fim. O serviço entregue é igual; o que muda é como o trabalho é organizado por baixo — e isso decide qual contratar para o seu prédio.

A escolha entre elas acontece num ponto bem concreto: qual starter você coloca no pom.xml/build.gradle. Daí a importância de acertar o nome — e os nomes mudaram.

Por que importa

Porque a variante errada arrasta um stack inteiro para o seu projeto. Não é uma flag de configuração que você troca depois; é a fundação web da aplicação.

Se você é um time servlet/MVC tradicional e adota, por inércia, o gateway reativo, acabou de trazer WebFlux e Netty para dentro de casa — um modelo de programação diferente, com regras próprias de debug e de não-bloqueio. Um Thread.sleep, um JDBC bloqueante ou um cliente HTTP síncrono no lugar errado e você trava o event loop do Netty, derrubando a vazão de tudo. Esse custo é real, e é exatamente o que a variante WebMVC existe para evitar: ela deixa você ter um gateway sem sair do mundo servlet que o time já domina.

Do outro lado, se você já é reativo — sua aplicação é WebFlux, seu time conhece Mono/Flux e backpressure —, escolher a variante MVC seria abrir mão do modelo não-bloqueante justamente onde ele rende mais: um ponto de altíssima concorrência de I/O de rede, que é o cenário-tese do reativo.

E há a armadilha de tooling que afeta os dois: os starters foram renomeados no trem 2025.x. Tutoriais, respostas de fórum e até notas suas de 2023-2024 ainda citam os nomes antigos. Colar o nome velho num projeto novo é o erro mais comum desta nota — e nem sempre o erro é óbvio no log.

Como funciona

A variante reativa — WebFlux/Netty

O Gateway Server WebFlux é o gateway original e não-bloqueante. Ele assenta sobre o stack Spring WebFlux, que por sua vez roda sobre o servidor Netty. Starter:

  • Atual (2025.x): spring-cloud-starter-gateway-server-webflux
  • Antigo: spring-cloud-starter-gateway

O ponto que a documentação crava: esse gateway exige o runtime Netty fornecido pelo Spring Boot + Spring WebFlux. Ele não roda num container servlet tradicional nem empacotado como WAR. Ou seja, ao escolher a variante reativa, você está escolhendo o stack reativo inteiro — não dá para “só usar o gateway” sem ele.

Fronteira de galho — Galho 11 (Programação Reativa)

WebFlux, Netty, event loop, não-bloqueio e backpressure são o assunto do Galho 11. Esta nota não re-explica o modelo reativo — ela só registra que a variante WebFlux do gateway é construída sobre ele. Se a dúvida for “como o event loop não-bloqueia?” ou “o que é backpressure?”, a resposta está lá, não aqui. Aqui você decide qual variante adotar; lá você entende como o reativo funciona por dentro.

Quando faz sentido: time já reativo, ou cenário de altíssima concorrência de I/O onde o não-bloqueio rende a vazão que justifica o stack. É também a variante com o ecossistema mais maduro de filters e predicates, por ser a histórica.

A variante MVC — servlet/bloqueante

O Gateway Server WebMVC é a variante mais nova, construída sobre o stack Spring MVC (servlet) e, portanto, bloqueante. Starter:

  • Atual (2025.x): spring-cloud-starter-gateway-server-webmvc
  • Antigo: spring-cloud-starter-gateway-mvc

A razão de existir é direta: nem todo mundo quer o stack reativo. Um time com aplicação MVC tradicional, threads por requisição e bibliotecas bloqueantes (JDBC, clientes HTTP síncronos) ganhava um peso desproporcional só para colocar um gateway na frente — tinha que aprender WebFlux, lidar com o event loop, vigiar bloqueios. A variante WebMVC remove esse imposto: o gateway roda no mesmo modelo servlet que o time já usa.

A contrapartida honesta é que você abre mão do não-bloqueio. Num gateway de pura intermediação de rede — onde I/O domina — o modelo bloqueante consome mais threads sob alta concorrência do que o reativo. Para muitos cenários, isso é perfeitamente aceitável; o ponto é que é uma troca consciente, não um detalhe.

Quando faz sentido: time servlet/MVC sem fluência reativa, projeto que não quer introduzir Netty/WebFlux, ou onde a simplicidade do debug síncrono vale mais do que o ganho de vazão do reativo.

A renomeação dos starters — e quando cada um

No trem 2025.x, os starters do gateway foram renomeados para deixar explícito que existem duas variantes de servidor. O esquema de nome velho não dizia qual stack você estava trazendo; o novo diz, no próprio artefato (-server-webflux vs -server-webmvc):

VarianteStackModeloStarter atual (2025.x)Starter antigo
ReativaWebFlux/Nettynão-bloqueantespring-cloud-starter-gateway-server-webfluxspring-cloud-starter-gateway
MVCSpring MVC (servlet)bloqueantespring-cloud-starter-gateway-server-webmvcspring-cloud-starter-gateway-mvc

O critério de escolha, em uma frase: siga o stack do seu time.

SituaçãoEscolha
Aplicação/time já reativo (WebFlux)WebFlux (-server-webflux)
Altíssima concorrência de I/O, vazão é o gargaloWebFlux
Time servlet/MVC tradicional, sem fluência reativaWebMVC (-server-webmvc)
Não quer introduzir Netty/WebFlux no projetoWebMVC
Debug síncrono simples vale mais que vazão de I/OWebMVC

Não há uma variante “certa” universal. Há a variante coerente com o resto da aplicação. O pior dos mundos é misturar: gateway reativo num time que escreve tudo bloqueante (veja Armadilhas).

Na prática

A mesma escolha — um gateway na frente de um orders-service — declarada nas duas variantes. Você inclui apenas UMA das dependências abaixo, conforme o stack do time.

Variante reativa (WebFlux/Netty):

<!-- VARIANTE REATIVA — sobre WebFlux/Netty (não-bloqueante) -->
<!-- Nome ATUAL (trem 2025.x). Antigo: spring-cloud-starter-gateway -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway-server-webflux</artifactId>
</dependency>

Variante MVC (servlet/bloqueante):

<!-- VARIANTE MVC — sobre o stack servlet (bloqueante) -->
<!-- Nome ATUAL (trem 2025.x). Antigo: spring-cloud-starter-gateway-mvc -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway-server-webmvc</artifactId>
</dependency>

O mesmo par no Gradle (Kotlin DSL), para deixar inequívoco que é uma ou outra:

// Escolha UMA. Não inclua as duas no mesmo módulo.
 
// --- Reativa (WebFlux/Netty) ---
implementation("org.springframework.cloud:spring-cloud-starter-gateway-server-webflux")
 
// --- MVC (servlet) ---
implementation("org.springframework.cloud:spring-cloud-starter-gateway-server-webmvc")

A configuração de rota em application.yml tem a mesma forma nas duas variantes — predicates e filters casam um caminho e encaminham para o serviço-alvo:

spring:
  cloud:
    gateway:
      routes:
        - id: orders-route
          uri: http://orders-service
          predicates:
            - Path=/api/orders/**
          filters:
            - StripPrefix=1

O que não muda: o conceito de gateway, predicates, filters e roteamento — isso é a nota 10. O que muda é o stack web por baixo, decidido inteiramente pelo starter que você escolheu acima.

Armadilhas

(1) Usar o nome de starter antigo (pré-renomeação)

spring-cloud-starter-gateway e spring-cloud-starter-gateway-mvc são os nomes antigos, anteriores ao trem 2025.x. Tutoriais, respostas de Stack Overflow e snippets de 2023-2024 ainda os usam à vontade — e copiar de lá num projeto novo no trem 2025.x é o erro mais frequente desta nota. Os nomes atuais são spring-cloud-starter-gateway-server-webflux (reativo) e spring-cloud-starter-gateway-server-webmvc (MVC). Ao iniciar um projeto, confira o nome contra a documentação da versão do seu trem, não contra o primeiro blog que o Google trouxer.

(2) Gateway reativo num time sem experiência WebFlux

Adotar a variante WebFlux “porque é a padrão dos tutoriais” num time que nunca escreveu código reativo é comprar uma dívida silenciosa. Debug reativo é diferente: stack traces longos e indiretos, backpressure a entender, event loop a respeitar. Tudo isso é território do Galho 11 — e se o time não tem essa base, a variante WebMVC entrega o gateway sem o pedágio de aprendizado. Não escolha o stack reativo por inércia; escolha-o porque o time o domina ou porque a vazão de I/O o exige.

(3) Misturar I/O bloqueante no gateway reativo

Se você escolheu a variante reativa, o compromisso é não bloquear o event loop. Um Thread.sleep, um acesso JDBC bloqueante, um cliente HTTP síncrono ou qualquer chamada bloqueante dentro de um filter trava a thread do Netty — e como pouquíssimas threads atendem toda a carga, um único bloqueio derruba a vazão do gateway inteiro. É a contradição clássica: você pagou o preço do stack reativo e, ao injetar código bloqueante, perde justamente o benefício pelo qual pagou. O como não-bloquear corretamente é assunto do Galho 11; o alerta aqui é que escolher WebFlux é assumir essa disciplina — se o time não vai segui-la, a variante MVC é mais honesta.

Em entrevista

Frase pronta (inglês)

“Spring Cloud Gateway actually ships in two live server variants today, and you pick one at the dependency level. The reactive one — spring-cloud-starter-gateway-server-webflux — runs on the WebFlux/Netty stack and is non-blocking; it’s the original gateway. The newer one — spring-cloud-starter-gateway-server-webmvc — runs on the servlet stack and is blocking, and it exists for teams that don’t want to pull the whole reactive runtime in just to have a gateway. Both starters were renamed in the 2025.x release train: the reactive one used to be spring-cloud-starter-gateway and the MVC one used to be spring-cloud-starter-gateway-mvc, so a lot of older tutorials still show the old names. My rule is simple: if the team is already reactive or I’m in a high-concurrency I/O scenario, I go WebFlux; if it’s a traditional servlet/MVC team with no reactive fluency, I go WebMVC — because dropping blocking I/O into a reactive event loop is the fastest way to throw away the benefit I paid for.”

Vocabulário

PortuguêsInglês
não-bloqueantenon-blocking
servletservlet
reativoreactive
contrapressãobackpressure
iniciador (de dependência)starter
tempo de execuçãoruntime
laço de eventosevent loop
trem de releaserelease train

Veja também

Referências

  • Spring Cloud Gateway Server WebFlux — Starter. docs.spring.io/spring-cloud-gateway/reference/spring-cloud-gateway-server-webflux/starter.html — artefato spring-cloud-starter-gateway-server-webflux; gateway reativo exige o runtime Netty (Spring Boot + WebFlux), não roda em container servlet nem como WAR. (acesso 2026-06-12)
  • Spring Cloud Gateway Server Web MVC — Starter. docs.spring.io/spring-cloud-gateway/reference/spring-cloud-gateway-server-webmvc/starter.html — artefato spring-cloud-starter-gateway-server-webmvc; variante sobre o stack servlet, para quem não quer o stack reativo. (acesso 2026-06-12)
  • Spring Cloud Gateway — Reference (5.0.x). docs.spring.io/spring-cloud-gateway/reference — as duas variantes de servidor (WebFlux e Web MVC) e seus stacks. (acesso 2026-06-12)