When you break a monolithic web backend into a decoupled microservices architecture, you run into an immediate structural problem: How do multiple independent applications share a single public domain name without clashing?
If you have an API and a background worker running in the same cluster, you don't want to force your API consumers to use completely different domains or track custom network ports (like port 3000 vs port 4000).
Instead, you want a unified routing gateway:
://my-portfolio-domain.com-> Goes to the AI engine://my-portfolio-domain.com-> Goes to the text worker
The standard solution is to use a shared NGINX Ingress Controller to map routes based on the URL path. However, this introduces a classic backend pitfall: The Subpath 404 Error.
If the Ingress forwards the request path /api/predict straight to your backend app container as-is, your Express or Fastify router will throw a 404 Not Found error because your application code expects a clean root request (/predict).
Here is how to master the NGINX rewrite-target annotation to dynamically strip away external subpaths, allowing your microservices to communicate seamlessly behind a single gateway.
The Path Stripping Router Architecture
The NGINX Ingress Controller uses powerful Regular Expression (regex) captures to intercept incoming subpath strings at the front door, clean them up, and pass the normalized path down to the hidden app pods.
External Traffic: http://my-domain.com
│
▼
┌─────────────────────────────┐
│ NGINX Ingress Front Gate │ (Listens on single public IP)
└──────────────┬──────────────┘
│
│ 1. Matches Path: /api/?(.*)
│ 2. Strips '/api' via regex capture
▼
┌─────────────────────────────┐
│ Private ClusterIP Service │ (Internal network only)
└──────────────┬──────────────┘
│
▼
┌─────────────────────────────┐
│ TypeScript App (app.ts) │ (Receives clean '/' route)
└─────────────────────────────┘
🛠️ Step-by-Step Implementation
To model a professional, enterprise-grade architecture, we pull the Ingress resource completely out of the individual microservice subfolders and place it in a centralized, global directory: infrastructure/global-ingress.yaml.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: global-microservices-ingress
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
# 🧠 THE MAGIC ENGINE: Captures the regex group $1 and overrides the request path
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: my-local-ai-service.com
http:
paths:
# 🤖 ROUTE 1: Forward /api/predict to the AI Inference application
- path: /api/?(.*)
pathType: ImplementationSpecific
backend:
service:
name: my-ai-app-service # Private ClusterIP service name
port:
number: 80
# 📊 ROUTE 2: Forward /processor/process to the Data Processor worker
- path: /processor/?(.*)
pathType: ImplementationSpecific
backend:
service:
name: my-processor-service # Private ClusterIP service name
port:
number: 80
🧠 Decoding the Regex Handshake: /?(.*) and /$1
How exactly does this text transformation operate under the hood?
- The Capture Group
/?(.*): When a user triggers an API request to/api/predict, the Ingress regex parser matches the route. The/?marks the trailing slash as optional, and the(.*)captures everything that follows it (in this case,predict) and saves it inside an internal variable named$1. - The Rewrite Target
/$1: The NGINX server strips the original path string away entirely, handles the internal network jump, and rewrites the incoming path to matching/$1(which maps to/predict). - Decoupled Application Logic: Your TypeScript application code remains completely clean and isolated. It doesn't need to know it is hosted behind a proxy gateway or a subpath sub-tree. It simply boots up, runs its strategy patterns, and responds on its native endpoints.
🚀 The Architectural Benefits
- Clean Domain Preservation: Your entire multi-service ecosystem operates under a single domain name, dramatically simplifying SSL/TLS certification setups (HTTPS handling at the front door) and frontend API integrations.
- Granular Network Isolation: Your actual business logic applications are hidden cleanly behind
ClusterIPnetworks. They are entirely inaccessible from the outside world except through the specific paths explicitly approved inside theglobal-ingress.yamlmanifest.
Conclusion
Mastering the Ingress rewrite target is the key to decoupling networking from business logic. By implementing centralized path routing, you transform isolated container apps into a unified, enterprise-ready microservices mesh.