Querystring Schemas

Type-Safe Filters & Pagination

Querystring Schemas

schema.querystring validates and coerces the URL search parameters, applying defaults and rejecting unknown filters.

4 min read Level 2/5 #fastify#schemas#querystring
What you'll learn
  • Declare querystring with a JSON Schema object
  • Coerce numeric and boolean query params
  • Apply defaults so handlers stay clean

The querystring schema applies to whatever comes after ? in the URL. Like params, values arrive as strings — coercion and defaults make them useful.

app.get('/posts', {
  schema: {
    querystring: {
      type: 'object',
      properties: {
        page: { type: 'integer', minimum: 1, default: 1 },
        pageSize: { type: 'integer', minimum: 1, maximum: 100, default: 20 },
        q: { type: 'string', maxLength: 200 },
        sort: { type: 'string', enum: ['new', 'top', 'old'], default: 'new' },
      },
    },
  },
  handler: async (req) => {
    const { page, pageSize, q, sort } = req.query;
    return await db.posts.search({ page, pageSize, q, sort });
  },
});

A request to /posts?page=2&pageSize=50 will arrive with req.query.page === 2 (a number), and /posts alone will see page: 1, pageSize: 20, sort: 'new'.

Repeated Keys and Arrays

const querystring = {
  type: 'object',
  properties: {
    tag: {
      type: 'array',
      items: { type: 'string' },
    },
  },
} as const;

Fastify’s default querystring parser (fast-querystring) handles ?tag=js&tag=ts as { tag: ['js', 'ts'] }. Pair with the schema above for compile-time safety.

Reject Unknown Filters

Set additionalProperties: false to refuse queries with extra keys — handy for catching deprecated filter names and obvious abuse.

Response Schemas →