Mapping Examples
Real-world patterns for response mapping.
E-commerce: Products with Categories
Enrich a product list with full category data from a separate service:
routes:
- method: GET
route: /products
service: product-service:3000
path: /products
public: true
mapping:
- path: /categories?id={categoryId}
service: catalog-service:3001
tag: category
removeKeyMapping: true
Backend returns:
[
{"id": "1", "name": "Laptop", "price": 2500, "categoryId": "c1"},
{"id": "2", "name": "Mouse", "price": 49, "categoryId": "c2"}
]
Gateway returns:
[
{
"id": "1",
"name": "Laptop",
"price": 2500,
"category": {"id": "c1", "name": "Electronics"}
},
{
"id": "2",
"name": "Mouse",
"price": 49,
"category": {"id": "c2", "name": "Accessories"}
}
]
Blog: Posts with Author and Comments
Enrich posts with data from two different services:
routes:
- method: GET
route: /posts
service: blog-service:3000
path: /posts
mapping:
- path: /users/{authorId}
service: user-service:3001
tag: author
removeKeyMapping: true
- path: /comments?postId={id}
service: comment-service:3002
tag: comments
removeKeyMapping: false
Gateway returns:
[
{
"id": "1",
"title": "Getting Started with Go",
"author": {"name": "Alice", "avatar": "alice.jpg"},
"comments": [
{"text": "Great article!", "user": "Bob"},
{"text": "Very helpful", "user": "Charlie"}
]
}
]
The frontend renders a complete blog post card with a single API call.
User Profile: Single Object with Orders
Mapping works on single objects too, not just arrays:
routes:
- method: GET
route: /users/{userId}
service: user-service:3000
path: /users/{userId}
mapping:
- path: /orders?userId={id}
service: order-service:3001
tag: orders
removeKeyMapping: false
- path: /addresses?userId={id}
service: address-service:3002
tag: addresses
removeKeyMapping: false
Gateway returns:
{
"id": "1",
"name": "Alice",
"email": "alice@example.com",
"orders": [
{"id": "o1", "product": "Laptop", "status": "shipped"},
{"id": "o2", "product": "Mouse", "status": "delivered"}
],
"addresses": [
{"type": "home", "city": "Florianopolis"}
]
}
Dashboard: Companies with Users
Recursive-style mapping — companies with their users:
routes:
- method: GET
route: /companies
service: company-service:3000
path: /companies
mapping:
- path: /users?companyId={id}
service: user-service:3001
tag: employees
removeKeyMapping: false
Gateway returns:
[
{
"id": "1",
"name": "Acme Corp",
"employees": [
{"name": "Alice", "role": "Engineer"},
{"name": "Bob", "role": "Designer"}
]
}
]
Inventory: Products with Stock and Supplier
Three mappings from three different services:
routes:
- method: GET
route: /inventory
service: product-service:3000
path: /products
mapping:
- path: /stock/{id}
service: inventory-service:3001
tag: stock
removeKeyMapping: false
- path: /suppliers/{supplierId}
service: supplier-service:3002
tag: supplier
removeKeyMapping: true
- path: /pricing/{id}
service: pricing-service:3003
tag: pricing
removeKeyMapping: false
All three mappings run in parallel for each product. With 100 products, that's up to 300 goroutines running concurrently — but with connection pooling and mapping cache, the actual HTTP calls are minimized.
Tips
Keep mapping targets fast. The gateway's response time = backend response time + slowest mapping. If a mapping target is slow, consider:
- Enabling mapping cache (
mappingCache.enabled: true) - Adding an index on the queried field in your database
- Using a lighter endpoint that returns only the fields you need
Use removeKeyMapping: true for clean APIs. Foreign keys like categoryId are implementation details — your API consumers care about the category name, not the ID.
One route can have many mappings. They all run in parallel. Adding more mappings adds latency only if the new mapping target is slower than the existing ones.