Edge and serverless functions run the same Application Password and Basic Auth pattern as every other client in this course, but the runtime itself introduces three practical questions that a long-lived Next.js server or a mobile device don’t have in the same form: where does the secret actually live when there’s no persistent server process, how does cold-start latency interact with an extra network hop to WordPress, and should a read-only ability’s result be cached rather than fetched fresh on every single invocation. This lesson covers all three, using real platform mechanisms rather than invented WordPress-specific tooling.
The Next.js server-side pattern from Lesson 3, and familiarity with your deployment platform’s environment variable and caching mechanisms (Vercel, Cloudflare Workers, or similar).
Step 1: Where the secret lives with no persistent server
A traditional server process reads an environment variable once at startup and keeps it in memory. An edge or serverless function has no equivalent long-lived startup, each invocation is provisioned and torn down independently, sometimes on a different underlying machine. The secret still comes from the same place conceptually, a platform-managed secret store, Vercel environment variables, Cloudflare Workers secrets, AWS Lambda environment variables backed by Secrets Manager, but it’s injected fresh into each invocation’s environment rather than persisting across a long-running process:
// File: app/api/latest-post-title/route.ts (Edge Runtime)
export const runtime = 'edge';
export async function GET() {
const auth = btoa(`${process.env.WP_APP_USERNAME}:${process.env.WP_APP_PASSWORD}`);
const res = await fetch(
`${process.env.WP_BASE_URL}/wp-json/mcp/v1/my-plugin/get-latest-post-title`,
{
method: 'POST',
headers: { Authorization: `Basic ${auth}`, 'Content-Type': 'application/json' },
body: JSON.stringify({}),
}
);
return new Response(await res.text(), {
status: res.status,
headers: { 'Content-Type': 'application/json' },
});
}
The code looks identical to the Node.js Route Handler from Lesson 3. The real difference is operational: verify your specific platform’s secret is actually scoped to server-side edge execution and not accidentally exposed to any client-side edge middleware that runs differently.
Some platforms distinguish between edge middleware that can touch request/response objects visible to the client and edge functions that run fully server-side. Read your specific platform’s documentation on secret scoping before assuming an “edge” secret is automatically as protected as a traditional server-only environment variable, the protections are similar in intent but the enforcement details differ by provider.
Step 2: Cold starts and the extra network hop
Every edge or serverless invocation that calls out to WordPress adds at least one full network round trip on top of whatever cold-start time the platform itself needs to initialize the function. For a rarely called endpoint, this might mean the first request after a period of inactivity pays both costs (cold start plus network round trip) while subsequent, warm requests only pay the network round trip. Two general, non-WordPress-specific mitigations apply here, same as they would for any external API call from an edge function: keep the function’s own logic minimal so cold-start initialization stays fast, and place your WordPress site’s hosting geographically close to where your edge functions execute, since the network hop, not WordPress’s own processing, is often the larger variable in total latency.
Step 3: Caching read-only ability results
Not every ability call needs a fresh answer every time. An ability marked
readonly in its meta.annotations (Course 1) is a strong signal that its result is a
reasonable caching candidate, at least for a short window. Two standard, general
approaches apply, neither of them WordPress-specific:
// File: app/api/latest-post-title/route.ts (HTTP-level caching hint)
export const runtime = 'edge';
export async function GET() {
// ...same fetch as Step 1...
const res = await fetch(/* ... */);
const body = await res.text();
return new Response(body, {
status: res.status,
headers: {
'Content-Type': 'application/json',
'Cache-Control': 's-maxage=30, stale-while-revalidate=60',
},
});
}
This Cache-Control header lets your platform’s own CDN or edge cache serve repeated
requests for up to 30 seconds without re-invoking the function at all, falling back to
a background revalidation for the following 60 seconds. For results that need to be
shared and invalidated more deliberately, a platform key-value store (Vercel KV,
Cloudflare KV, or similar) works as an explicit cache keyed by the ability name and its
input:
// File: app/api/latest-post-title/route.ts (explicit KV cache, illustrative)
const cacheKey = 'ability:my-plugin/get-latest-post-title';
const cached = await kv.get(cacheKey);
if (cached) {
return Response.json(cached);
}
const fresh = await callAbility(/* ... */);
await kv.set(cacheKey, fresh, { ex: 30 });
return Response.json(fresh);
Caching is appropriate for abilities marked readonly, and even then, only for a
window your application can tolerate being stale. An ability that writes, publishes, or
deletes something should never be served from a cache instead of actually executing,
doing so would silently skip the real action while returning a stale success response.
Step 4: What never belongs in the cache
Whatever caching layer you use, cache only the JSON result the ability returned, never the Application Password or the Basic Auth header used to obtain it. The credential is read fresh from the platform’s secret store on every invocation that needs to make a new outbound call, it has no business sitting in a KV store or CDN cache alongside the data it fetched.
Test it: confirm a cached response actually avoids the extra call
Add temporary logging inside your fetch function, then hit your cached endpoint twice in quick succession:
console.log('Calling WordPress at', new Date().toISOString());
You should see the log line once for the first request, and not again for a second request within your cache window, confirming the cache is actually short-circuiting the network call rather than silently re-fetching every time.
Recap
Edge and serverless functions use the identical Application Password and fetch pattern
as every other client in this course, injected fresh from a platform secret store on
each invocation rather than read once at server startup. Cold-start time and the
network round trip to WordPress are additive and separately worth minimizing.
Read-only, readonly-annotated abilities are reasonable candidates for short-lived HTTP
or KV-based caching, but the credential itself never belongs in that cache, only the
resulting data does. The next lesson closes the loop on security: locking down CORS and
rate limiting for whichever of these external callers reaches your MCP and abilities
endpoints directly.
Resources & further reading
- Vercel Edge Functions, vercel.com
- Cloudflare Workers, developers.cloudflare.com
- Abilities API reference, developer.wordpress.org