Adding Pagination To Vapor Query

When you have a request that returns many records, it’s almost required to paginate the response.

I found this QueryContainer extension that does just that:

QueryContainer extension

import Foundation
import Vapor
import Fluent

public struct BasicQuery: Codable {
    public let plain: Bool?
    public let page: Int?
    public let limit: Int?
    public let search: String?

extension QueryContainer {
    public var basic: BasicQuery? {
        let decoded = try? decode(BasicQuery.self)
        return decoded
    public var plain: Bool? {
        return basic?.plain
    public var page: Int? {
        return basic?.page
    public var limit: Int? {
        return basic?.limit ?? 20
    public var search: String? {
        return basic?.search

//GET http://localhost:8080/api/countries?limit=20&page=1
extension QueryBuilder {
    public func paginate(on req: Request) throws -> Self {
        if let limit = req.query.basic?.limit {
            let page = req.query.basic?.page ?? 0
            let lower = (page * limit)
            return range(lower: lower, upper: (lower + limit))
        return self


//GET /api/countries
aRoute.get(use: getAllPaginatedHandler)
func getAllPaginatedHandler(_ req: Request) throws -> Future<[CountrySQLite]> {
    return try CountrySQLite.query(on: req).paginate(on: req).all()


To fetch 10th page, given that a page size is 20 records:

GET http://localhost:8080/api/countries?limit=20&page=10

You may checkout the full example on GitHub:


Prev: Parent-Child relationships in Generic Fluent Models

Next: Revert Last Migration

Vapor 3 Tutorial Start

#pub #query #fluent #swift #pagination