Project 4.4: Web Caching Fallback (E-commerce App)
I am pursuing a Master's in Communication Systems and Networks at the Cologne University of Applied Sciences, Germany.
๐งฐ PREREQUISITES:
EC2 Instance:
t2.medium(Ubuntu 24.04)Security Group: Open port
30000-32767for NodePort
๐ง STEP 1: Install Docker, Minikube, kubectl
1. Install Docker
sudo apt update -y
sudo apt install -y docker.io curl
sudo systemctl enable docker
sudo systemctl start docker
2. Add user to Docker group
sudo usermod -aG docker $USER
newgrp docker # or logout and log in again
3. Install Minikube
bashCopyEditcurl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
rm minikube-linux-amd64
4. Install kubectl
K8S_VERSION=$(curl -s https://dl.k8s.io/release/stable.txt)
curl -LO https://dl.k8s.io/release/${K8S_VERSION}/bin/linux/amd64/kubectl
chmod +x kubectl
sudo mv kubectl /usr/local/bin/
๐ STEP 2: Start Minikube
Start Minikube with enough resources
minikube start --driver=docker --memory=3072mb --cpus=2
Use Minikube Docker for image build
bashCopyEditeval $(minikube docker-env)
๐ STEP 3: Build Node.js E-commerce App
1. Create index.js
vim index.js
Paste:
๐ STEP 3: Build Node.js E-commerce App
1. Create index.js
vim index.js
Paste:
const express = require('express');
const app = express();
app.use(express.json());
let products = [
{ id: 1, name: "Laptop", price: 999 },
{ id: 2, name: "Phone", price: 599 }
];
app.get('/products', (req, res) => res.json(products));
app.post('/products', (req, res) => {
const product = req.body;
product.id = products.length + 1;
products.push(product);
res.status(201).json({ message: 'Product added' });
});
app.listen(3000, () => console.log('E-commerce app running on port 3000'));
2. Create package.json
vim package.json
Paste:
{
"name": "node-ecommerce",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"express": "^4.18.2"
}
}
3. Create Dockerfile
vim Dockerfile
Paste:
FROM node:18
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "index.js"]
4. Build Docker image
docker build -t node-ecommerce:latest .
๐ STEP 4: Set Up Nginx Caching
1. Create config folder and file
mkdir nginx
cd nginx
vim default.conf
Paste:
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=10m;
server {
listen 8080;
location / {
proxy_pass http://localhost:3000;
proxy_cache my_cache;
proxy_cache_valid 200 10s;
add_header X-Proxy-Cache $upstream_cache_status;
}
}
โ๏ธ STEP 5: Kubernetes Files
1. Create deployment.yaml
vim deployment.yaml
Paste:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ecommerce-app
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: ecommerce
template:
metadata:
labels:
app: ecommerce
spec:
containers:
- name: node-app
image: node-ecommerce:latest
imagePullPolicy: Never # Use local image in Minikube
ports:
- containerPort: 3000
- name: nginx
image: nginx:latest
ports:
- containerPort: 8080
volumeMounts:
- name: config-volume
mountPath: /etc/nginx/conf.d/
volumes:
- name: config-volume
configMap:
name: nginx-config
2. Create service.yaml
vim service.yaml
Paste:
apiVersion: v1
kind: Service
metadata:
name: ecommerce-service
spec:
selector:
app: ecommerce
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: NodePort
๐งฑ STEP 6: Deploy App to Minikube
1. Create ConfigMap for Nginx
kubectl create configmap nginx-config --from-file=nginx/default.conf
eval $(minikube docker-env)
2. Apply Deployment and Service
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
3. Check pod and service
kubectl get pods
kubectl get svc
๐ STEP 7: Access the App
Open service
minikube service ecommerce-service

or manually:
curl -i http://<minikube-ip>:<nodeport>/products
curl -i http://192.168.49.2:30993/products

โ You should see a list of products and:
X-Proxy-Cache: MISS
๐ STEP 8: Test Fallback Caching
1. Make a request to /products twice:
curl -i http://<minikube-ip>:<port>/products
Second time โ You should see:
X-Proxy-Cache: HIT
๐ How to See HIT Instead of EXPIRED
Immediately run this within 10 seconds:
curl -i http://192.168.49.2:30993/products
You should now get:
X-Proxy-Cache: HIT

2. Kill Node.js container
kubectl get pods
kubectl exec -it <pod-name> -c node-app -- kill 1
# kubectl exec -it ecommerce-app-5d9d64c87d-d5xs4 -c node-app -- kill 1
3. Make request again
curl -i http://<minikube-ip>:<port>/products
#curl -i http://192.168.49.2:30993/products
โ You should still get data from cache:
X-Proxy-Cache: HIT
๐ Revised Project Report for 4.4 โ Fallback by Means of Web Caching
Title:
4.4 Fallback by Means of Web Caching
Focus Area:
๐ก๏ธ Resilience in microservice communication
Description:
System X consists of several microservices. These services communicate via an intermediate HTTP server, specifically an Nginx proxy. The aim of this project is to implement a fallback mechanism using web caching to maintain service availability when a backend service becomes temporarily unavailable.
Research Questions:
Is web caching a suitable fallback solution for microservices?
What are the pitfalls of relying on caching during failures?
How should Nginx be configured for optimal caching in Kubernetes?
What HTTP cache headers must be handled at the application layer (Node.js)?
Approach:
Deploy Nginx as a sidecar container within the same Kubernetes Pod of the backend microservice.
Let all outgoing and incoming HTTP traffic be proxied by Nginx.
Use Nginx caching directives and shared volumes to store and serve cached content.
Implement cache headers and control behavior in Node.js (Express) application.
Simulate service failure and observe whether Nginx can continue to serve cached data.
Technology Stack:
Kubernetes: Minikube for local orchestration
Docker: Containerization of Node.js app
Nginx: HTTP caching and proxying
Node.js (Express): E-commerce microservice
Ubuntu 24.04 on EC2 (
t2.mediuminstance)
Architecture Diagram:
[Kubernetes Pod]
โโโ Container 1: Node.js (API)
โโโ Container 2: Nginx (Sidecar Proxy)
โ
[Client Requests]
โ
Nginx (cache / proxy)
โ
Node.js App
Implementation Summary:
Created a simple
/productsAPI withGETandPOSTin Node.js.Configured Nginx with
proxy_cache,proxy_cache_path, andproxy_cache_validfor 10s duration.Built both containers and deployed to the same Pod using Kubernetes.
ConfigMap mounted for Nginx configuration.
Kubernetes NodePort service exposed the app externally.
Tested Scenarios:
| Test | Expected Result | Outcome |
First GET /products | Fetch from backend | โ MISS |
Second GET /products <10s | Serve from cache | โ HIT |
| Backend container killed | Serve cached content | โ HIT |
| After 10s with backend down | Cache expired, fails | โ EXPIRED |
Findings:
โ Caching works reliably within timeout period.
โ Can handle short-term service outages without affecting client.
โ ๏ธ Stale data risk if cache duration is too long.
โ ๏ธ Requires manual cache control headers in backend (e.g., ETag, Cache-Control).
Nginx Configuration Sample:
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=10m;
server {
listen 8080;
location / {
proxy_pass http://localhost:3000;
proxy_cache my_cache;
proxy_cache_valid 200 10s;
add_header X-Proxy-Cache $upstream_cache_status;
}
}
HTTP Header Setup in Node.js (if extended):
res.set('Cache-Control', 'public, max-age=10');
res.set('ETag', generateETag(data)); // optional
Conclusion:
Web caching using Nginx as a sidecar is an effective short-term fallback for microservices. It reduces downtime impact, increases perceived uptime, and simplifies load handling during failure spikes. However, developers must carefully manage cache invalidation and header configurations to avoid stale or incorrect data.