The two methods you described are the only available methods to achieve such a thing.
If you have 100 records returned and you want to paginate by 20 (5 pages), then the difference between one method or the other is negligible. If you have 1000 records returned and you want to paginate by 20 (50 pages), then the best method is fire a "count" and a separated limitby for retrieving the records. Remember you can fire a db(query).count() and cache that: the record count will be fetched one time only and from then on from the cache and the db will be hitted only by the limitby query. e.g. total = db(db.pages.active==True).count(cache=(cache.ram,120)) records = db(db.pages.active==True).select(limitby=(0,20))