Skip to content
cccskills
FreePublished on GitHub

fastly-multi-service-routing-debug

Debug Fastly Compute services where code changes don't affect behavior due to multi-service routing architecture. Use when: (1) deployed changes have no effect, (2) unexpected redirects persist after code updates, (3) DNS resolves to Fastly but responses don't match deployed code, (4) `fastly service list` shows multiple related services. The root cause is often a routing/gateway service intercepting requests before they reach your content service.

The English summary is being prepared. Showing the original description.

See how to install

Files included (1)

  • SKILL.md4.8 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

Fastly Multi-Service Routing Debug

Problem

You deploy changes to a Fastly Compute service but the behavior doesn't change. Requests still return old responses, redirects, or errors even after:

  • Deploying new code with fastly compute publish
  • Purging the cache with fastly purge --all
  • Verifying the correct service version is active

Context / Trigger Conditions

  • DNS resolves to Fastly IPs (151.101.x.x)
  • Response headers show x-served-by: cache-xxx (Fastly cache)
  • Deployed code should return different status/headers but doesn't
  • Multiple Fastly services exist for the same project (e.g., divine-web, divine-router)
  • Wildcard subdomain routing is involved (*.example.com)

Solution

Step 1: Identify Which Service Handles the Domain

# List all services
fastly service list

# Check which service handles your domain using domain-v1
fastly domain-v1 list | grep your-domain.com

The output shows the service ID for each domain:

*.divine.video      glh3AfBEmZKzmAmByvGyAg  76fTayX6mBKa8faLeZ1fet  2025-12-28...
divine.video        1JttvGPc6AlOVg4koUGhPg  76fTayX6mBKa8faLeZ1fet  2025-11-23...

The third column is the service ID that handles that domain.

Step 2: Verify Service Architecture

Common patterns:

  • Router + Content: A routing service (often Rust) sits in front, handling subdomain logic, then passes through to a content service
  • Gateway Pattern: Edge gateway handles auth/rate-limiting, then proxies to origin
  • Wildcard Routing: *.domain.com may be handled by a different service than domain.com

Step 3: Debug the Correct Service

Once you identify the routing service:

# Check its active version
fastly service-version list --service-id <router-service-id>

# Check its domains
fastly domain list --service-id <router-service-id> --version active

# Find and read its source code (usually in a different repo)

Step 4: Trace Request Flow

Add debug logging to understand the flow:

  1. In the routing service: log the Host header and routing decision
  2. In the content service: log if requests are even reaching it
  3. Check Fastly logs: fastly log-tail --service-id <id>

Step 5: Fix the Correct Service

If the routing service is doing unwanted redirects:

  • Update its routing logic to pass through instead of redirect
  • Or update it to return the desired response directly
  • Deploy to the routing service, not just the content service

Verification

# Test with cache bypass
curl -sI -H "Cache-Control: no-cache" "https://subdomain.your-domain.com/?t=$(date +%s)"

# Verify new behavior appears
# Check response headers match what your code should return

Example

Symptom: rabble.divine.video returns 301 redirect despite divine-web having code to serve HTML directly.

Discovery:

$ fastly domain-v1 list | grep divine.video
*.divine.video      ...  76fTayX6mBKa8faLeZ1fet  ...  # This is divine-router!
divine.video        ...  76fTayX6mBKa8faLeZ1fet  ...  # Same - router handles both

Root Cause: divine-router (Rust service) was returning 301 redirects in its serve_profile() function, never letting requests reach divine-web.

Fix: Updated divine-router to return the desired response directly instead of redirecting.

Notes

  • The fastly domain list command shows domains on a specific service/version
  • The fastly domain-v1 list command shows ALL domains across ALL services
  • Wildcard domains (*.domain.com) often route to a different service than apex
  • When using Fastly Compute backends, the request may go: Router → Content → Origin
  • Cache purging only affects the service that's caching; if a router caches, purge there
  • Response headers like x-publisher-server-collection indicate which service responded

Architecture Patterns

Pattern 1: Router → Content

User → DNS → Fastly Router Service → Fastly Content Service → Origin/KV Store

The router handles subdomain logic, auth, or routing rules.

Pattern 2: Direct

User → DNS → Fastly Content Service → Origin/KV Store

Single service handles everything.

Debugging Tip

If you're unsure which pattern applies, check the [setup.backends] section in each service's fastly.toml to see if one service proxies to another's edgecompute.app URL.

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

Fix ArgoCD ExternalSecret deployment failing with "namespace X is not permitted in project Y". Use when: (1) ExternalSecret shows OutOfSync in ArgoCD but won't sync, (2) ArgoCD application status shows "namespace X is not permitted in project 'infrastructure'", (3) ExternalSecret targets a namespace managed by a different ArgoCD project, (4) Using apps-of-apps pattern with separate infrastructure and application projects.

The English summary is being prepared. Showing the original description.

divinevideo/divine-mobile266Updated Oct 19, 2026

Art direction for any content — reads text, PDF, Word, HTML, PPT, then proposes 2-3 creative directions with photography style, mood, and visual language. After selection, generates AI image prompts and visual briefs section-by-section. Use when the user shares content and needs visual direction, image sourcing, or creative direction for any material.

The English summary is being prepared. Showing the original description.

divinevideo/divine-mobile266Updated Oct 19, 2026

Fix "Null check operator used on a null value" errors when an object is set to null during an async await. Use when: (1) Object reference is nullified while awaiting, (2) Code accesses object with ! after await returns, (3) Cancel/dispose operations run concurrently with async operations on same object. Solution: capture local reference before await.

The English summary is being prepared. Showing the original description.

divinevideo/divine-mobile266Updated Oct 19, 2026

Add custom metadata headers (x-amz-meta-*) to AWS v4 signed requests for GCS S3-compatible API. Use when: (1) Adding custom metadata to GCS uploads via S3 API, (2) Getting signature mismatch errors after adding new headers, (3) x-amz-meta-* headers being ignored or causing 403 errors. Custom headers MUST be included in canonical headers and signed headers list.

The English summary is being prepared. Showing the original description.

divinevideo/divine-mobile266Updated Oct 19, 2026

Fix password/secret authentication failures caused by trailing newlines when creating Google Cloud secrets (or similar) with bash here-strings. Use when: (1) Password authentication fails with correct password, (2) Secret created with `<<< "value"` syntax, (3) Error like "password authentication failed" or "invalid token" despite correct value. Bash here-strings (`<<<`) add a trailing newline that corrupts secrets.

The English summary is being prepared. Showing the original description.

divinevideo/divine-mobile266Updated Oct 19, 2026

Fix silent video/media processing failures caused by URL extraction code that filters on file extensions (.mp4, .webm, .webp). Use when: (1) Media moderation, transcoding, or analysis silently skips files from Blossom or content-addressed storage servers, (2) URL extraction from Nostr event tags (imeta, r tags) drops URLs without recognized extensions, (3) CDN fallback URLs append .mp4 but the actual server uses extensionless content-addressed paths like /{sha256}. Common in Nostr video events (kind 34236) where different clients use different URL formats.

The English summary is being prepared. Showing the original description.

divinevideo/divine-mobile266Updated Oct 19, 2026

See all skills by divinevideo

Report a problem with this skill