Course outline

Svelte / Intermediate: Kit routes and server data policy / Lesson 8

Server and universal load data contracts

Choose where load executes and return only authorized serializable data while controlling source work and reruns.

About 4 min readContent reviewed
On this page

Lesson goals

  • Distinguish server-only and universal load execution and serialization.
  • Validate source shape and bound independent reads without creating waterfalls.

A load file selects an execution boundary

A +page.server or +layout.server load runs on the server, while a universal +page or +layout load can participate in server rendering and subsequent browser navigation under Kit’s rules. Server-only credentials and source clients must stay behind the server boundary. Returned server data crosses a serialization boundary and must be suitable for the page’s audience. Kit supports more than plain JSON through its documented data serialization, but that technical capability does not authorize disclosure. A server load can still leak a secret if it returns it deliberately. Keep a narrow DTO and source eligibility in the same reviewed domain contract.

Read current locals and return a public model

The server-load fragment uses route params and a principal established in event.locals by a reviewed server hook. It registers an application dependency label for later targeted invalidation. locals is request-scoped context, not proof that the principal is authentic; the hook and service must enforce that contract. The helper returns a narrow eligible card and handles source absence under application policy. No Kit load, hook, fetch or serializer was executed here. Do not import this private helper into a universal load file and assume its original server location protects the browser dependency graph.

javascript Illustrative server-load boundary
// src/routes/courses/[id]/+page.server.js
export async function load({params,locals,depends}) {
  depends("app:course-card");
  const course=await catalog.visibleCard(locals.principal,params.id);
  return {course};
}

catalog and principal establishment are assumed. No request context or dependency rerun was created.

Use the request-aware fetch contract deliberately

Kit’s supplied fetch has framework behavior for relative/internal requests and server rendering that differs from treating global fetch as universally interchangeable. Follow documented credential forwarding and response-header rules for the actual destination; never forward a private token to every caller-provided URL. Validate HTTP status and source shape separately. Avoid fetching an application’s own endpoint from a server load when an authorized domain helper provides the same capability more directly. Keep expected absence distinct from transport failure, malformed payload and denied scope, with safe public outcomes and controlled internal correlation.

Validate one source payload without emulating load

The plain validator accepts a synthetic card with text id/title and projects only those fields. It rejects wrong shape before any renderer receives the value. This is not a full schema system or authorization engine, and real contracts may add version, length and tenant checks. Parsing JSON alone recognizes syntax, while a TypeScript assertion changes static belief without changing received data. The assertions are local and open no connection. Verify actual Kit serialization and load reruns separately, including how errors are translated before data reaches page props or shared layout context.

javascript Complete offline source-card validator
function validCard(value){
  if(!value || typeof value!=="object" || Array.isArray(value) || typeof value.id!=="string" || typeof value.title!=="string")throw new Error("INVALID_CARD");
  return {id:value.id,title:value.title};
}
console.assert(validCard({id:"c1",title:"Loading",internal:"omit"}).title==="Loading");
let rejected=false;try{validCard({id:"c1",title:7});}catch{rejected=true;}console.assert(rejected);

A valid card is projected and a wrong-type title rejects. No Kit load or source request is executed.

Bound source work and declare the dependencies that matter

Independent source reads need not wait sequentially, but creating a promise per unbounded item can overload a pool. Bound cardinality and concurrency before starting work. Calling parent unnecessarily early can create a load waterfall when data could be fetched independently. Track params, URL values and explicit depends labels under the documented invalidation rules rather than assuming every navigation reruns every load. Rendering and preloading should be side-effect free. This course executes only the source validator; it does not run load scheduling, parent composition, credential forwarding, invalidation or source cancellation. Real verification needs the selected Kit adapter and safe isolated fixtures.

Common errors and fixes

A universal load imports private source credentials

Why it happens
Server-only implementation and browser-capable execution were mixed.
How to fix it
Move private source access behind a server-only load/helper boundary.
Prevent it next time
Review the browser import graph and returned data separately.

A valid JSON response contains an invalid card

Why it happens
Syntax parsing replaced runtime shape and domain checks.
How to fix it
Validate received records and project the page model.
Prevent it next time
Test wrong types, absence and source failure independently.

Unnecessary parent waiting creates a slow waterfall

Why it happens
Independent reads were serialized by the load structure.
How to fix it
Identify real dependencies and schedule bounded independent work appropriately.
Prevent it next time
Measure safe source-stage timing without adding overlapping spans blindly.

Check your understanding

1. Does returning a value from a server load make it private?

Show worked solution

No. Returned data is intended for the page and can cross to the browser under the serialization contract. Keep credentials server-only, enforce object eligibility and return only the approved public or principal-scoped model. Test output keys as well as the import boundary.

2. Why does the source validator not prove load invalidation works?

Show worked solution

It receives an ordinary object and has no Kit dependency graph, navigation or request context. Invalidation requires the load to read tracked inputs or declare the correct dependency and the caller to invalidate that dependency. Verify the actual rerun and displayed revision in an authorized integration.

Key takeaways

  • Load execution and returned-data disclosure are separate boundaries.
  • Track meaningful dependencies and bound source work before rendering.

Official references