Skip to main content
This guide connects an existing CloudFront distribution to Dynamic Bot Rendering. This setup adds one CloudFront Function on viewer request to select an origin for eligible AI assistant page requests. This setup uses no Lambda@Edge. Two properties support this integration:
  • With viewer Host forwarding disabled, CloudFront uses the custom origin domain for its Host header and TLS Server Name Indication (SNI). Preserve this setting in both policies in step 3.
  • Profound’s CloudFront endpoint returns cache-control: no-store itself, so CloudFront never stores a second, staler copy of content Profound already caches.
Requests routed to Profound use the CloudFront endpoint GET https://concierge.tryprofound.com/v1/concierge/cloudfront/{path}. You never construct that URL by hand. The origin’s Origin path setting prepends the prefix, and the request URI passes through untouched.

Why the design looks like this

Two CloudFront rules shape everything below:
  1. A viewer-request function can’t change which cache behavior a request matches. CloudFront selects the behavior before the function runs, and rewriting the URI doesn’t re-match it. Assistant traffic therefore stays in the same behavior as human traffic, rather than a dedicated behavior with its own cache policy.
  2. A viewer-request function can switch the origin, including building a per-request origin group with failover (cf.createRequestOriginGroup, runtime cloudfront-js-2.0).
Two consequences follow:
  • Routing happens by swapping the origin, not the behavior. Because Origin path is a per-origin setting, a failover to your default origin automatically uses the original, unprefixed path. No path rewriting is needed.
  • Assistant and human requests share the behavior’s cache policy, so the cache key must be split with a marker header (step 3). Without it, CloudFront can serve a human-cached copy to an assistant, or the reverse.

Prerequisites

  • An existing CloudFront distribution
  • AWS Identity and Access Management (IAM) permissions for CloudFront distributions, functions, and cache policies
  • Your Dynamic Bot Rendering API key, a registered domain, an effective serving policy, and a known published test page. See Before you start.
  • Public, non-personalized pages only. The example allows /, /pricing, /docs, and /docs/getting-started. Replace these with reviewed public pages; do not include APIs, authentication, account, admin, or framework-resource paths.
  • Record existing function associations, origins, and policies for rollback. Preserve existing security, authentication, and rewrite logic. If combining it requires a routing design change, stop and review that separately.
  • Confirm that firewall rules, bot challenges, and origin allowlists permit both assistant traffic and Profound’s origin/scraper fetches. The loop marker is not an authentication or firewall bypass.

Setup

1

Create the Profound origin

Open CloudFront → Distributions → your distribution → Origins → Create origin.Add two custom origin headers:CloudFront overwrites any viewer-sent header of the same name when forwarding to this origin, so a client can’t spoof the API key or the host. The function in step 2 also strips them, for defense in depth.
Serving more than one hostname from this distribution? A static x-concierge-host only works for a single public host, and static origin headers win over anything the function sets. For a multi-domain distribution, omit that custom header here, uncomment the marked line in the function below, and include x-concierge-host in the cache key in step 3 so it is also forwarded. Forwarding alone does not separate cached responses for different hosts. Review host identity for human and fallback responses too before enabling multiple hosts.
2

Create the viewer request function

Open CloudFront → Functions → Create function. Name it profound-bot-rendering and choose the runtime cloudfront-js-2.0. Origin groups require the 2.0 runtime.
Replace YOUR_DEFAULT_ORIGIN with your distribution’s existing default origin ID and PUBLIC_HOSTS with the registered hosts for this origin, then select Publish. For the static host header, list only that one host. Keep the exact public-path allowlist aligned with your site’s routes. Requests with cookies or authorization keep their existing routing; the function does not send them to Profound.The function routes only GET; all other methods return to existing routing. CloudFront origin groups support failover for GET, HEAD, and OPTIONS. The configured 503 criterion enables connection-failure failover; 504 enables response-timeout failover. Before deployment, set and record a bounded primary-origin connection-attempt, connection-timeout, and response-timeout budget that leaves time for the fallback request. CloudFront defaults can spend 30 seconds on connection attempts alone (three attempts of 10 seconds). Test the resulting total latency; do not assume failover is immediate. See CloudFront origin failover.
3

Update the cache and origin request policies

CloudFront strips any viewer header or query string the behavior’s policies don’t include. This happens before the origin request, regardless of what the function decided. Three settings are required on the behavior serving your pages.1. Add x-concierge-route to the cache-key headers. AWS managed cache policies can’t be edited. If the behavior uses one, copy every setting into a new custom policy first, then add the header. Keep Minimum TTL (time to live) at 0. In the multi-domain variant, include the trusted x-concierge-host in cache identity as well as forwarding it. The bot marker alone does not distinguish hosts.2. Include the query strings your pages vary on (or “All”) in the cache key. Cache-key query strings also reach the origin. An origin request policy can forward additional query strings without keying them, but responses that vary on those values can then share a cache entry. If neither policy includes a query string, CloudFront strips it. Verify both forwarding and cache identity for each supported variant.3. Forward the viewer User-Agent through the origin request policy. By default, CloudFront replaces User-Agent with Amazon CloudFront on origin requests. Profound would then classify every routed request as an unknown agent and permanently fail open, with no renders served and none scheduled. Use a custom header allowlist for User-Agent and, when required, Accept and Accept-Language (plus x-concierge-host in the multi-domain case). Preserve required compression settings. Do not use AllViewer: viewer Host forwarding can override the service hostname and break origin routing or TLS. Exclude viewer Host, Cookie, and Authorization from both the cache and origin request policies; cache-key values are forwarded too. These policies apply to human traffic as well. If the existing behavior needs these headers or cookies, stop and review compatibility before changing it. CloudFront documents per-origin originOverrides for hostHeader and sni in request origin groups; a customer origin requiring a different host needs that compatibility reviewed separately. This example does not choose or add an override. Profound’s origin fetches do not forward viewer credentials, and published pages are not per-session or per-language variants.
For this setup, add User-Agent to the origin request policy rather than the cache key. An origin request policy applies to the whole behavior, so CloudFront now forwards the viewer User-Agent on human requests too. If your origin varies its HTML by User-Agent (separate mobile and desktop markup, for example) without corresponding cache-key variation, CloudFront can serve one cached variant to other viewers. Confirm that the existing cache key already accounts for your origin’s variants. Locale, geography, and other header-dependent content also need review. If this requires a cache design change, stop before deployment. Raw User-Agent keying can substantially reduce cache reuse.
4

Associate the function with the behavior

Open Behaviors → your page behavior → Edit. Set the cache policy from step 3, then under Function associations set Viewer request to your profound-bot-rendering CloudFront Function. For a behavior without existing edge logic, no origin request or origin response association is needed. Do not remove existing associations. Merge and preserve existing viewer-request logic before associating this function; stop if that requires a design decision.Save and wait for the distribution to finish deploying.
5

Verify

Check the HTTP status, a valid x-concierge-request-id, and the expected x-concierge-bot-kind. On your known published page, also require x-concierge-cache: HIT and the expected rendered body. Test normal browser traffic, non-GET methods, excluded paths, and credential-bearing requests against their existing behavior.Test CDN-level failover only in staging or an isolated distribution. Record the original origin settings, configure an unreachable test origin, and repeat an uncached assistant request. Expect the default-origin response after the configured timeout, with no x-concierge-request-id. Restore the original settings and wait for propagation. A 401 does not trigger failover; the configured 400 and 403 statuses do, which can mask configuration errors. Cached fallback responses can persist until their TTL expires.Full checks and header meanings are in Verify and troubleshoot.

How the cache split behaves

  • Human requests never carry the marker, because the function strips any client-supplied copy. The marker separates their entries from assistant entries, but query and header policy changes can affect human cache hit rates.
  • Eligible assistant requests carry x-concierge-route: bot and get their own entries.
  • Profound’s responses set cache-control: no-store, so with Minimum TTL at 0 the assistant-keyed entries are only ever populated by failover responses from your own origin: correct content, expiring on your origin’s own TTL.
During a full Profound outage, failed-over origin responses can sit in the assistant-keyed cache until their TTL expires, delaying the return to rendered content after recovery.Validate that this recovery delay is acceptable for your existing TTLs. Changing how fallback responses are cached requires a separate design review; this guide does not add an edge function to change that behavior.

Rolling back

Restore the recorded viewer-request association and any policies changed for this setup. Use No association only if there was no previous function. Allow the configuration to propagate, then verify the original routing and cache behavior. Previously cached fallback responses can remain until their TTL expires or they are invalidated through your normal process.