Harper × Lowes

Context-Aware Redirects

An Akamai EdgeWorker in Lowe's existing request path calls into a Harper application for context-aware routing. Decisions made at request-time against live inventory, Pro status, geography, and caller type — not at config-time in Akamai Edge Redirector Cloudlet or nginx rules. Zero changes to origin.

The Problem

Lowe's has accumulated millions of redirect rules across seven years of modernization, the December 2024 Rithum / Mirakl marketplace launch, the October 2025 FBM acquisition adding 370 new distribution locations, and ongoing SKU churn. Those rules live in Akamai Edge Redirector and nginx — static config with no runtime access to the data that would make routing correct. Googlebot, Rufus, ChatGPT, and Google's UCP Business Agent all hit the same URLs and get HTML designed for humans.

Millions
Redirect rules in static config
Across Akamai + nginx, accumulated over 7 years
Dec 2024
Rithum / Mirakl marketplace
3P SKU explosion. Catalog churn outpaces config deploys
Oct 2025
FBM acquisition closed
370 new locations, Pro catalog doubled, URL spaces merged
4+ agents
Bots all get the same HTML
Googlebot, GPTBot, ClaudeBot, Google UCP Business Agent

Demo: Four Callers, One URL

Pick a real lowes.com URL. Hit trigger. Four legitimate callers — Googlebot, a Pro contractor near Charlotte NC, a DIY shopper in San Francisco, and a GPTBot AI agent — all send the same URL to Harper simultaneously. Harper makes five real routing decisions from live data. A fifth "no Harper" lane shows current production behavior for contrast. Every response you see below is from a real Harper backend call.

Request URL (real scraped lowes.com)
SKU status: Inventory: Vector match:
URL 1 scenario: Discontinued Kobalt impact wrench. A reasonable alternative exists (DeWalt or Craftsman equivalent) in Lowe's catalog. Today this is a broken chain — category redirect with no SKU-level context. Harper resolves inventory + Pro status + geography at the edge and picks the right destination per caller.
DIY auth as Pro:
flip on → DIY lane sends a pro_id cookie → Harper returns the Pro-priced alt
Agent method:
GET (flip for POST → watch 303 swap to 307 method-preserved)

Googlebot

Search index crawler
User-Agent: Googlebot/2.1

Press trigger

Pro Contractor

Charlotte, NC · logged in
Cookie: pro_id=8841 · 35.23°N

Press trigger

DIY Shopper

San Francisco, CA · guest
37.73°N → store #1652

Press trigger

AI Agent

GPTBot / ChatGPT-User
User-Agent: GPTBot/1.2

Press trigger

Current lowes.com

Akamai + nginx · no Harper
Static config, no runtime data

Press trigger

Live Harper Stats

Total decisions0
Avg latency
0
301
0
302
0
303
0
307
0
308
0
410

Response-Code Matrix

Two URLs down, six columns across. Every cell is a different status code and destination, selected at request time from live data. Zero static definitions in the database for these specific combinations. Zero code deploys to change any of them.

URL Googlebot Pro (Charlotte) DIY (SF) AI Agent (GET) AI Agent (POST) No Harper
URL 1: discontinued SKU
/pd/Kobalt-Cordless-Impact-Wrench/1000595395
301
canonical collapse
302
Pro-priced alt
302
local alt, store #1652
303
/api/product/…
307
method preserved
Soft-404
/cat/tools/
URL 2: discontinued, no alt
/pd/GE-Profile-Electric-Range/5001234567
410
Gone · crawl-budget safe
302
close-but-not-equiv Pro
302
geo-alt SF Bay
303
/api/related/…
307
POST preserved
404
dead end

301 Canonical Moves

Permanent SKU renames or URL-structure migrations. Today: observed as multi-hop chains. Harper: collapse to one hop at the edge using the redirect graph in MQTT-synced state.

Passes PageRank, saves crawl budget

302 Inventory-Dependent

The target depends on what's in stock right now at the caller's store, whether Pro pricing applies, and vector-search similarity of alternatives. Static config cannot express this — Harper resolves it per request.

Correct destination for every shopper

303 Structured for Agents

Detected AI agents (GPTBot, ClaudeBot, Google UCP Business Agent, Rufus) are redirected to machine-readable JSON endpoints instead of HTML bundles. Faster, cheaper, and the agent actually gets the data it needs.

Right format for the caller

307 / 308 Method Preserved

When an agent POSTs to a moved URL, standard 302 silently downgrades to GET — data is lost. Harper returns 307 (temporary) or 308 (permanent) so POST stays POST. Critical for agent-driven checkout flows.

No silent data loss on agent actions

410 Gone (not Soft-404)

When a SKU is permanently gone with no reasonable substitute, Harper returns 410. Google drops the URL from the index fast and reallocates crawl budget. Current lowes.com returns a soft-404 redirect to a category page — wastes crawl budget for little SEO value.

Crawl-budget safe

Data, not Code

Caller detection patterns, routing rules, and SKU alternative graphs live in Harper tables. Updates propagate via MQTT to every edge node in seconds. Lowe's merchandising updates a redirect without a PR, a deploy, or a pager rotation.

Minutes instead of quarters

How the decision is made

An Akamai EdgeWorker sits in Lowe's existing request path. For URLs flagged as discontinued or moved, the EdgeWorker calls into a Harper application over HTTPS, passes the request context, and emits the 3XX response based on Harper's decision. Harper holds the data (inventory, Pro accounts, redirect graph, caller rules, alternative-product vectors) and runs the pipeline. The EdgeWorker stays thin.

Caller

Googlebot · Pro · DIY · GPTBot · UCP Agent

Akamai EdgeWorker

Thin shim in front of origin. On a flagged URL, calls Harper for the decision, then emits the 3XX.

Harper application

POST /RedirectDecision · classify caller · vector search · inventory + Pro + geo filter · pick status

3XX Response

301 · 302 · 303 · 307 · 308 · 410 — emitted by the EdgeWorker

Harper endpoints the EdgeWorker calls

POST /RedirectDecision GET /RedirectStats GET /Seed (one-time demo setup) GET /Debug/:what (ops)

Data colocated with the Harper application (MQTT-synced from Lowe's systems)

Inventory (live stock, per store) SKU redirect graph Pro account + pricing table Store locator (geo → nearest store) Caller classification rules Alternative-product vectors (HNSW)

How vector search finds alternatives in Harper

When a shopper, crawler, or agent hits a discontinued SKU, Harper has to find the best live alternative — from the product catalog now expanded by Rithum/Mirakl marketplace additions and the FBM acquisition. Brute-force cosine comparison against every product scales linearly with catalog size. Harper avoids that by using its built-in HNSW (Hierarchical Navigable Small World) vector index, declared directly in the schema.

1

The schema declares the index

One directive on a [Float] field creates an HNSW index on the column. No separate vector database to run, no sync pipeline to keep in step with the catalog, no second query language.

type Product @table @export { id: ID @primaryKey name: String @indexed description: String embedding: [Float] @indexed(type: "HNSW", distance: "cosine") }

Harper supports cosine and euclidean distance. Tunable parameters include optimizeRouting and efSearchConstruction; sensible defaults work for most workloads.

2

Seed stores the embeddings inline with the row

When the Seed resource loads products, each one's name + description is converted to a 384-dim vector and written on the same record. The HNSW index is updated as each row is inserted — no separate indexing step, no rebuild.

await tables.Product.put({ id: 'p_dw_imp_bare', name: 'DEWALT 20V MAX Impact Wrench (Bare Tool)', description: 'cordless impact wrench 1/2 inch drive 20V max brushless...', embedding: textToVector(name + ' ' + description) // [0.023, -0.145, 0.891, ...] });

The demo's textToVector is a token-ngram bag-of-words hashed into 384 buckets — good enough to cluster products by shared vocabulary. For production, swap that one function for a Voyage, OpenAI, or self-hosted bge-small call. The rest of the pipeline doesn't change.

The discontinued SKU's embedding lives on the RedirectRule row itself (searchEmbedding), not in Product — because it's gone from the catalog. One vector, seeded once, describes what the dead URL meant.

3

Two query patterns, both native to Harper

Harper exposes HNSW search through the same tables.X.search() method as any other query. Two patterns depending on what you need:

A. Top-K nearest neighbors (the idiomatic pattern for "show me the most similar")
tables.Product.search({ sort: { attribute: 'embedding', target: queryVec }, limit: 5, }) // returns the 5 products closest to queryVec, ordered by cosine distance
B. Distance-threshold filter (the pattern this demo uses)
tables.Product.search({ conditions: { attribute: 'embedding', comparator: 'lt', // return only candidates within the threshold value: 0.75, // cosine distance < 0.75 target: queryVec, }, limit: 10, }) // returns candidates within threshold, up to 10 — may be fewer, may be zero

Pattern B is used here because we want "only suggest an alternative if it's actually similar enough" — beyond the threshold we prefer to return a 410 rather than redirect to something loosely related. The threshold is evaluated against the index during traversal, not by loading candidates and computing distance in JavaScript.

4

Candidate set is small, then filtered further

Whichever pattern is used, the search returns at most a handful of candidates. Harper then filters that set by live inventory at the caller's nearest store, applies Pro-catalog preference ranking, and picks a destination. The expensive "what's similar in the catalog" step runs against the graph index; the cheaper "what's in stock and Pro-priced" steps run against a list of 10 things.

Full catalog
millions of SKUs
HNSW search
graph traversal
~10 candidates
within threshold
Inventory filter
in stock at store
Pro sort
Pro-catalog first
1 destination
returned to caller

Why HNSW vs brute-force

Brute-force distance comparison against every vector is O(N) — it scales linearly with catalog size. HNSW is a multi-layer graph where upper layers have long edges between distant nodes and lower layers are dense. Search descends layer by layer, converging on the neighborhood of the query vector. Expected time is roughly O(log N). The tradeoff is that results are approximate — the true top-K may occasionally be replaced by a very close neighbor.

Why colocated, not a separate vector DB

A typical stack has the app server, a row database, and a vector database on three different networks. Every request pays round-trip tax to each. In Harper, the catalog rows, the HNSW index, the inventory rows, and the application code all run in the same process. The candidate list goes straight from the index into the inventory filter with no serialization boundary.

Why cosine specifically

Cosine distance measures the angle between two vectors, ignoring magnitude. Two product descriptions that use similar vocabulary in different amounts still match if they're about the same thing. Euclidean distance would penalize the length difference. Both are supported in Harper — cosine is the default for text embeddings.

Why a threshold fits this demo

Top-K would always return 5 candidates, even when the closest one isn't actually close. For a redirect decision that's the wrong shape: we'd rather return 410 Gone than route to a loosely-related product and give a bad SEO or shopping signal. A threshold lets the search itself say "nothing similar enough" and the pipeline responds accordingly.

Why an EdgeWorker shim

Akamai already terminates TLS, handles caching, and owns the request path at Lowe's edge. The EdgeWorker is a small script that runs inside that existing infrastructure. For most URLs it does nothing — origin is hit directly. For a flagged URL, it makes one HTTPS call to Harper and emits the response Harper returned.

Why Harper holds the data

Akamai EdgeWorkers have strict CPU and memory budgets and no persistent store. They can't hold millions of inventory rows, run HNSW vector search, or join Pro accounts against geo. Harper can — it's a database with the application logic colocated. The EdgeWorker asks, Harper answers.

Data sync

Lowe's inventory + commerce feeds publish to MQTT. Harper subscribes. Changes propagate across the Harper Fabric mesh in seconds — merchandising flips a redirect rule and every Harper node sees it without a deploy, a config PR, or a cache-invalidation dance.

What Harper Delivers

Everything Akamai Edge Redirector + nginx gives today, plus everything neither can do because they don't have the data.

Drop-in replacement

Covers everything Akamai Edge Redirector Cloudlet does today. Akamai EdgeWorker sits in the same request path, calls Harper for the decision, emits the 3XX. Rules and destinations live in Harper tables.

No origin changes required

Inventory-aware routing

Redirect destination depends on what's actually in stock at the caller's nearest store right now.

No more 404s on out-of-stock alternatives

Pro-aware routing

Logged-in Pro accounts get Pro-priced alternatives and Pro desk pickup context in query string. Vector search against Pro catalog first.

FBM catalog integrated at the edge

Geography-aware routing

IP → nearest store from MaxMind + Lowe's store locator. Alternative must be in stock at that store, or the next-closest store with stock.

No cross-country stock-out surprises

Agent-aware routing

Googlebot, GPTBot, ClaudeBot, Google UCP Business Agent, Rufus all classified from User-Agent patterns stored as data. Each gets an appropriate response format.

JSON for agents, HTML for humans

Data, not code

Redirect rules, caller patterns, alternatives graph — all in Harper tables. Merchandising updates a redirect in minutes, not a quarter-long engineering cycle.

No code deploys to change routing

Revenue Recovery Model

Modeled against Digital Commerce 360's $12.17B projection of Lowe's 2025 online sales. Numbers below are projections — see assumptions panel for the math.

$194.7M
Projected annual revenue recovered
Projection · see assumptions · not a Lowe's-committed number

Inputs

Lowe's 2025 projected online sales$12.17B
$8B$15B
% of sessions hitting a redirect8.0%
1%20%
Current redirect drop-off rate40%
10%70%
Harper drop-off reduction50%
10%80%

Projected impact

Redirect-hitting sales (at risk)
$973M
sessions × AOV assumption
Currently lost to drop-off
$389M
before Harper
Recovered by Harper
$194.7M
annual
As % of 2025 online
1.6%
of $12.17B
Assumptions (tweak the sliders to test):
  • % of sessions hitting a redirect: industry range 5-15% on retail sites with 7 years of URL churn + recent marketplace + acquisition
  • Drop-off rate: fraction of redirect-hitting sessions that don't complete — current lowes.com returns category pages, 404s, and broken chains
  • Drop-off reduction: fraction recovered by routing to an in-stock, geo-local, Pro-aware alternative instead of a dead end
  • Conservative: no credit for SEO upside from 410-vs-soft-404 crawl-budget behavior, no credit for agent-driven revenue from UCP / ChatGPT shopping
Digital Commerce 360 (Nov 2025) — Lowe's 2025 online sales projected at $12.17B
Lowe's Q3 2025 earnings — FBM closed Oct 2025, 370 new locations, Pro catalog expanded
Google Search Central — 410 Gone removes URLs from the index faster than soft-404 and conserves crawl budget

Why now — mapped to Lowe's 2026 strategy

Everything in this demo connects to a public Lowe's priority for 2026. Harper isn't a hypothetical fit — it's directly in line with where money is already being spent.

1 FBM integration (Oct 2025)

Closed October 2025. 370 new distribution locations. FBM's catalog being linked into Lowe's Pro extended aisle. URL spaces need to merge without breaking search equity or Pro workflows.

"FBM is a leading distributor in interior building products. Gives us a more comprehensive product portfolio, expands revenue streams, and enhances our offering to Pro customers." — Marvin Ellison, Q3 2025
Harper: Merge URL spaces as data, route Pro to FBM-priced alternatives with Pro desk context

2 Rithum / Mirakl marketplace (Dec 2024)

3P SKU explosion. Marketplace catalog churn moves faster than Akamai config deploys. Each 3P de-list is a potential broken URL that static config won't catch for days.

Marketplace launched December 2024 via Rithum (formerly ChannelAdvisor) and Mirakl partnership
Harper: Inventory-driven routing catches de-lists at the edge in seconds via MQTT

3 Mylow + agent commerce

Mylow handles ~1M questions/month, doubles online conversion. Next wave: Google's UCP Business Agent, ChatGPT shopping, Claude computer use — all hitting lowes.com with HTML-fetching tools that would be much faster against JSON endpoints.

"When our customers engage with Mylow online, the conversion rate more than doubles." — Marvin Ellison
Harper: 303 to structured JSON for agents. Right format for the caller, saves agent latency and token cost

4 $2.5B capex, tech priority #1

Lowe's guided to $2.5B capex for 2026 with technology the leading investment category. Measurable ROI without disrupting core retail operations is explicitly called out.

"Capital expenditures of up to $2.5 billion" — Lowe's Q3 2025 guidance
Harper: Ship in days, not quarters. One EdgeWorker, zero origin changes, A/B-testable from day one
Harper × Lowe's POC · April 2026 · lowes.com ↗