Postgres supports cursors and documents them very well:
https://www.postgresql.org/docs/current/plpgsql-cursors.html
Basically, you declare a cursor like that:
DECLARE cname CURSOR FOR <select statement>;
You can pass the cursor’s name „cname“ (and even store it on the client side, although, best encrypted) and obtain the „next“ slice of your data corresponding to the query on demand like that:
FETCH next cname;
Not sure you really gain that much performance on everyday queries but with a large number of rows it might.