У вас может params[:limit] не приходит, вот и достаётся Post.all, т.е. все 20тыс записей.
Ещё может добавьте, чтобы поиск был не после ввода первого символа, а например после третьего.
Ещё можно добавить индексы в таблицу, если их нет.
Ещё, судя по тому коду, что вы написали, нет вообще как такового поиска по символу (нет where по простому)
Ещё, вы отдаёте наружу целиком данные, т.е. все колонки таблицы posts. Т.е. полагаю вам подойдёт что-то типа такого:
render :json => @posts.as_json(:only => [:title, :created_at])
Тогда данных будет отправляться на порядок меньше.