Skip to main content

Service Pillar Map

The service pillar map is the lookup table that tells InfraSage which tenant, product, and custom dimensions each service belongs to. Without mappings, services are silently excluded from Pillar Embedding scoring.

Data model​

Each entry maps one service_id to:

FieldTypeDescription
service_idstringMust match the service_id used in ingested telemetry
tenant_idstringKey for the tenant pillar. Empty string = not mapped
product_idstringKey for the product pillar. Empty string = not mapped
custom_keysmap[string]stringArbitrary key/value pairs for custom pillars

A service can belong to a tenant and a product at the same time, and it can appear in several custom dimensions at once.

Adding mappings​

Via UI​

  1. Open Pillar Embeddings in the sidebar
  2. Click the Service Map tab
  3. Paste CSV lines into the bulk import box (one service per line):
payment-service, acme-corp, checkout
auth-service, acme-corp, platform
worker-svc, beta-inc,

Format: service_id, tenant_id, product_id

Leave product_id blank if the service should only be mapped to a tenant.

  1. Click Apply. Changes take effect on the next vectorizer tick (≤ 60 s).

Via API​

Single or batch upsert​

curl -X PUT https://api.infrasage.dev/api/v1/pillars/service-map \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"entries": [
{
"service_id": "payment-service",
"tenant_id": "acme-corp",
"product_id": "checkout",
"custom_keys": { "region": "ap-south-1", "team": "payments" }
},
{
"service_id": "auth-service",
"tenant_id": "acme-corp",
"product_id": "platform",
"custom_keys": { "region": "us-east-1", "team": "platform" }
},
{
"service_id": "worker-svc",
"tenant_id": "beta-inc",
"product_id": "",
"custom_keys": {}
}
]
}'

The API upserts: sending the same service_id again, in one request or across several, keeps the latest values.

List current mappings​

GET /api/v1/pillars/service-map?limit=500

Automation​

At service deployment​

Add a mapping call to your CI/CD pipeline or Helm chart post-install hook:

# Example: inject mapping from Kubernetes labels
SERVICE_ID=$(kubectl get deployment $DEPLOYMENT -o jsonpath='{.metadata.labels.app}')
TENANT_ID=$(kubectl get deployment $DEPLOYMENT -o jsonpath='{.metadata.labels.infrasage.dev/tenant}')
PRODUCT_ID=$(kubectl get deployment $DEPLOYMENT -o jsonpath='{.metadata.labels.infrasage.dev/product}')

curl -X PUT https://api.infrasage.dev/api/v1/pillars/service-map \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"entries\": [{\"service_id\": \"$SERVICE_ID\", \"tenant_id\": \"$TENANT_ID\", \"product_id\": \"$PRODUCT_ID\", \"custom_keys\": {}}]}"

Bulk import from a CMDB or service catalog​

Export a CSV from your CMDB and use the API to load it:

# cmdb_export.csv: service_id,tenant_id,product_id,region
while IFS=',' read -r svc tenant product region; do
entries+="{\"service_id\":\"$svc\",\"tenant_id\":\"$tenant\",\"product_id\":\"$product\",\"custom_keys\":{\"region\":\"$region\"}},"
done < cmdb_export.csv

# Remove trailing comma and wrap
payload="{\"entries\":[${entries%,}]}"
curl -X PUT https://api.infrasage.dev/api/v1/pillars/service-map \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "$payload"

Custom keys​

Custom groupings read the custom_keys map. The key name in the map must be the key the pillar groups by: a region pillar reads "region", an az pillar "az", a team pillar "team".

A service without that key in custom_keys is left out of that custom pillar (it still counts toward the tenant and product pillars).

Viewing the map​

GET /api/v1/pillars/service-map?limit=1000

The Service Map tab of the Pillar Embeddings page shows the same list.

Required RBAC permission​

PUT /api/v1/pillars/service-map requires the modify:thresholds permission (available to operator role and above). GET is available to all authenticated roles.