When a user asks for all the words starting with “foobar” let’s check the cache for fooba,foob,foo,fo,f and see if any of these results already include a full set of words.
This saved us ~30% of our db queries and makes the ui more responsive.
# given a start word of foobar check caches for ["fooba", "foob", "foo", "fo", "f"] # to see if any of the simpler queries already had a complete response def cached_autocomplete(start) limit = 1000 short = start.dup shorter = Array.new(start.size - 1){ short.chop!.dup } cached = Rails.cache.read_multi(*shorter.map { |s| "autocomplete-#{s}" }) cached.each_value do |tags| if tags.size < limit # complete response / nothing is missing tags.select! { |t| t.start_with?(start) } # filter non-matches return tags end end Rails.cache.fetch("autocomplete-#{start}", expires_in: 15.minutes, race_condition_ttl: 1.minute) do ... hit the db ... limit(limit) ... ... prevent multiple cache refreshes with race_condition_ttl ... end end