CodeIgniter’s Active Record resets itself after every get(), which is what you want almost always and a nuisance exactly once per paginated listing: the total and the page of rows need the same joins and the same conditions, so they get written out twice and then drift apart. start_cache() marks everything up to stop_cache() as sticky.
$this->db->start_cache();
$this->db->from('orders')
->join('customers', 'customers.id = orders.customer_id')
->where('orders.status', 'paid');
$this->db->stop_cache();
$total = $this->db->count_all_results();
$rows = $this->db->limit(20, $offset)->get()->result();
$this->db->flush_cache();
The catch is the flush. Cached parts survive not merely the next query but every query for the rest of the request, so leaving flush_cache() out produces a bug that looks impossible from where it surfaces: some later, unrelated get() comes back filtered by a where that is nowhere near it. I have taken to writing the three calls as one block and deciding where the flush goes before writing anything in between. It caches the query being built and nothing else — the results are not cached by any of this.