Building Search That Does Not Suck: From Basic to Advanced in Web Applications
Search is the feature that every application needs and most applications do poorly. Bad search creates a terrible user experience — users cannot find what they know exists, they get irrelevant results, and they lose trust in the platform.
I have built search features five times at different scales, from a 100-item catalog to a 500,000-document index. Each time, I started too simple and had to rebuild. Here is the progression and when to jump to each level.
Level 1: SQL LIKE Queries (0-1000 items)
For very small datasets, a simple SQL LIKE query works:
SELECT * FROM tools WHERE name LIKE '%json%' OR description LIKE '%json%'
This is fine for prototyping and for catalogs under 1,000 items. It is trivial to implement (one WHERE clause), requires no additional infrastructure, and has no operational overhead.
Problems at scale: LIKE queries with leading wildcards (%term%) cannot use indexes. Performance degrades linearly with table size. No relevance ranking (all results are equally "relevant"). No typo tolerance. No synonym handling. No faceted filtering.
When to move on: when your catalog exceeds 1,000 items, when users complain about not finding things, or when you need features like "did you mean?" suggestions.
Level 2: Database Full-Text Search (1,000-100,000 items)
PostgreSQL and MySQL have built-in full-text search capabilities that are dramatically better than LIKE queries.
PostgreSQL uses tsvector (pre-processed text) and tsquery (search expressions). You create a tsvector column (or a generated column), add a GIN index, and query with the @@ operator. This gives you: word stemming (searching "running" matches "run"), ranking by relevance, phrase matching, and boolean operators (AND, OR, NOT).
MySQL has FULLTEXT indexes with MATCH AGAINST syntax. Similar capabilities: relevance ranking, boolean mode for complex queries, and natural language mode for simple searches.
Benefits over LIKE: uses indexes (fast even on large tables), relevance ranking (best matches first), stemming (language-aware matching), and stop word handling (ignoring "the," "is," "a").
Limitations: still not great at typo tolerance (misspelling "jsonn" will not match "json"), no synonym handling (searching "format" does not match "formatter" without stemming luck), limited faceting, and configuration is complex.
On AIDToolStack, we use database full-text search for our main tool search. We created a searchable text field that concatenates the tool name, description, category, and tags, then index it. Searches against 600+ tools return in under 10ms. Good enough for our current scale.
Level 3: Dedicated Search Engine (100,000+ items or advanced features)
When you need typo tolerance, faceted filtering, synonym handling, or sub-50ms search across large datasets, move to a dedicated search engine:
Meilisearch: the best developer experience in 2026. Drop-in replacement for basic search with instant results, typo tolerance, faceting, sorting, and filtering. Easy to self-host or use their cloud. We plan to migrate to this as we grow.
Typesense: similar to Meilisearch, excellent performance, good for e-commerce style search with filtering and faceting. Slightly more mature in production deployments.
Elasticsearch/OpenSearch: the enterprise standard. Handles massive scale (billions of documents), complex aggregations, and advanced analytics. Overkill for most applications but essential for large-scale log search or product catalogs.
Algolia: SaaS search. Zero infrastructure management. Excellent performance and features. Expensive at scale ($1+ per 1000 search requests) but worth it if you do not want to manage infrastructure.
Implementing Search Well
Regardless of which backend you use, good search requires thought at the UX level:
Instant results (search-as-you-type)
Users expect results to appear as they type, not after pressing Enter. Implement debounced search that fires after 150-300ms of typing pause. Show results in a dropdown below the search input. Allow keyboard navigation (arrow keys to select, Enter to open).
The performance requirement: results must appear within 200ms of the debounce firing. Users perceive anything slower as laggy. This means your search backend must respond in under 100ms (accounting for network latency).
Relevance ranking
Not all matches are equally relevant. A tool whose name matches the query is more relevant than one whose description mentions the term in passing. Weight your fields: name matches rank highest, then category, then description, then tags.
Test your ranking with real queries. Search for "json" — does JSON Formatter appear first? Search for "uuid" — does UUID Generator beat a blog post that mentions UUIDs? Adjust weights until common queries return expected results.
Typo tolerance
Users misspell things. "javascript" might be typed as "javasscript" or "javscript." A good search engine handles this automatically (Meilisearch, Typesense, Algolia all do). With database search, you can implement Levenshtein distance or trigram similarity (PostgreSQL's pg_trgm extension).
Empty state
When search returns no results, do not just show "No results found." Show: suggestions for alternative queries, popular items, or categories to browse. An empty search result is a dead end — give users a path forward.
Filters and facets
For large catalogs, allow filtering by category, price, rating, or other dimensions alongside text search. Faceted search shows the count of results in each category, helping users narrow their search.
Implementation: pass filter parameters alongside the search query. The search backend applies both the text match and the filters simultaneously. Show active filters as removable chips so users can easily modify their search.
Search Architecture
For our scale (600 tools, 200 AI products, 250 MCP servers, 130 blog posts):
The search endpoint receives a query and optional filters. It queries the database with full-text search. Results are weighted by content type (tools rank higher than blog posts for tool-related queries). Response includes the result items plus facet counts.
We index multiple content types in the search: tools, AI products, MCP servers, blog posts, guides, and comparisons. Each result type has a type field so the frontend can render appropriate cards.
Search Indexing
If using a dedicated search engine, you need to keep the search index in sync with your database:
Real-time sync: write to both the database and the search index on every mutation. This gives instant search freshness but adds complexity and a failure point (what if the search write fails?).
Async sync: write to the database, then emit an event. A consumer processes the event and updates the search index. Slight delay (seconds) between database write and search availability, but simpler and more resilient.
Scheduled full reindex: run a complete reindex on a schedule (every hour, every day). Simple to implement but search can be stale between reindexes. Acceptable for content that changes infrequently.
We use scheduled reindexing with on-demand reindex after content changes. When a new tool is added or a blog post is published, we trigger a reindex. Between changes, the search index reflects the last reindex.
Performance Optimization
Search is latency-sensitive. Users notice delays of 100ms. Optimize:
Cache popular queries. The top 100 search queries account for 80% of searches. Cache their results with a 5-minute TTL.
Limit result sets. Return 10-20 results per page. Do not compute all 500 matching results — paginate.
Use appropriate indexes. Database full-text search requires proper indexing (GIN for PostgreSQL, FULLTEXT for MySQL). Without indexes, every search scans the entire table.
Minimize payload. Return only the fields needed for display (title, excerpt, URL, type). Do not return full document bodies in search results.
When to Invest in Search
Search matters most when: your catalog exceeds 50 items (users cannot browse everything), users have specific intent ("I need a JSON formatter"), or discovery is a core value proposition of your platform.
Search can wait when: your catalog is tiny (under 20 items — just show them all), your content is primarily consumed via navigation (blog with category browsing), or your users arrive via direct links and rarely need to search.
Invest proportionally to the role search plays in your user experience. For a developer tools platform like AIDToolStack, search is critical — developers have specific needs and limited patience. We invest heavily in search quality because it directly impacts whether users find value in the platform.
Written by AIDToolStack Editorial
The AIDToolStack editorial team reviews developer tools, AI products, and MCP servers with hands-on testing and honest assessments. We use the tools we review every day in production.
References & Further Reading
Related Posts
Sponsor Our Newsletter
Reach thousands of developers who are actively evaluating AI tools, MCP servers, and dev infrastructure. Our weekly newsletter goes to engaged technical decision-makers.
All sponsored content is clearly labeled per our editorial policy.