Only Postgres: Why Your MVP May Not Need Redis, Elasticsearch, or a Vector Database Yet

Discover why many MVPs can start with PostgreSQL alone—and when Redis, Elasticsearch, queues, or vector databases become necessary.

Gabriel's avatar
Gabriel
Only Postgres: Why Your MVP May Not Need Redis, Elasticsearch, or a Vector Database Yet

SEO keyphrase: Only Postgres for MVPs


TL;DR

  • Most MVPs and small systems work very well with Only Postgres for MVPs, without Redis, Elasticsearch, or a dedicated vector database.
  • Modern PostgreSQL already handles simple caching, text search, filters, reports, basic queues, and even vector search through extensions.
  • Instead of guessing about bottlenecks too early, start simple, measure, and add new components only when the pain is real.
  • The goal is not “Postgres forever,” but “Postgres as a safe default” plus an architecture that can evolve later, with specialized tools when they make sense.

1. Context: Why Are We Complicating Things So Early?

Comparison of an MVP with Only Postgres and another with multiple services such as Redis, Elastic, a queue, and a vector database.
Comparison of an MVP with Only Postgres and another with multiple services such as Redis, Elastic, a queue, and a vector database.

A classic scene.

You open the repository of an MVP that does not even have ten users yet and find:

  • A microservices API—three or five services, obviously.
  • Redis for caching.
  • Elasticsearch for search.
  • A vector database “because we are going to use AI at some point.”
  • A queue—Kafka or RabbitMQ—“so we are ready to scale.”

And the business problem is still being defined.

This often turns into a kind of “LinkedIn résumé” architecture: a collection of sophisticated components, with little clarity about the actual need. The result is a team spending energy bringing up, configuring, monitoring, and debugging infrastructure while the product is still trying to discover whether anyone wants to use it.

Why does this happen so often?

  • Technical FOMO: fear of “falling behind” by not using the latest popular stack.
  • The wrong scale reference: copying Netflix’s or Meta’s architecture for a SaaS with 50 customers.
  • Confusing “it may be useful someday” with “I need it today.”

The thesis of this article is simple:

For many MVPs, Only Postgres for MVPs is a safer, cheaper, and easier-to-operate starting point. And if it succeeds, you can still evolve later.

This is not a manifesto against Redis, Elastic, or vector databases. These tools are excellent—in the right context. The focus here is the timing of complexity: delaying the cost of operating a technology zoo until you actually need it.

If you would like to see the same discussion in presentation format, check out the Only Postgres for MVPs talk, which explores this reasoning in another context.


2. What a Well-Used “Only Postgres” Setup Already Solves

Minimalist infographic highlighting PostgreSQL features such as BTREE and GIN indexes, JSONB, full-text search, and extensions.
Minimalist infographic highlighting PostgreSQL features such as BTREE and GIN indexes, JSONB, full-text search, and extensions.

Many people still see PostgreSQL only as “a relational database that handles CRUD and joins.” But modern PostgreSQL provides much more than that and covers several needs that teams outsource to other tools far too early.

Important PostgreSQL capabilities today

Some commonly underused features include:

  • Various index types
  • BTREE: the basic choice for equality and ordering.
  • GIN: excellent for indexing arrays, JSONB, and full-text search.
  • GiST: supports geometric data, proximity searches, and some full-text scenarios.
  • BRIN: useful for very large tables, especially when data is naturally ordered.

  • JSONB and semi-structured data

  • Lets you store less structured parts of the domain without leaving Postgres.
  • Useful for metadata, per-customer settings, integration payloads, and more.

  • Native full-text search

  • With tsvector / tsquery, stemming, basic ranking, and stop words.
  • You can build a reasonably capable search for titles, descriptions, and text content.

  • Extensions

  • pg_trgm: similarity search, useful for autocomplete and corrections.
  • pgvector: vector columns for AI—we will discuss this later.
  • Other extensions can solve specific niches, but for an MVP these two already cover a lot of ground.

  • Useful concurrency mechanisms

  • FOR UPDATE SKIP LOCKED, for example, allows you to implement concurrent queues in a task table, preventing two workers from processing the same record.

Together, these features already support use cases such as:

  • Simple caching.
  • Basic queues.
  • Text search.
  • More demanding reports and filters.
  • Early generative AI use cases with RAG.

This does not mean PostgreSQL replaces caching systems, distributed queues, search engines, or vector databases in every context. It means that, during the MVP phase, it is often “good enough” to avoid introducing those other components too early.

Architectural benefits of starting with a single database

When you choose Only Postgres for MVPs, several benefits appear naturally:

  • Fewer components → fewer failure points
  • One fewer instance—or cluster—to deploy, monitor, and pay for.
  • Less latency between services; many operations become simple database calls.

  • Simpler operations and observability

  • Centralized backups.
  • Monitoring focused on a single stack—Postgres metrics plus application logs.
  • Tuning concentrated in one place.

  • A team focused on the product

  • Less time configuring pipelines, operating queues, and deploying new services.
  • More time validating business hypotheses, listening to users, and improving the flow.

This reasoning is explored in more detail in the Only Postgres for MVPs analysis, which examines why many MVPs do not need to start with Redis, Elasticsearch, or a dedicated vector database.

Example: a simple B2B SaaS

Imagine a B2B SaaS product for managing sales proposals:

  • Basic entities:
  • User, company, customer, proposal, proposal item, attachment.
  • Features:
  • CRUD for customers and proposals.
  • Filters by status, date, amount, and owner.
  • Monthly report of approved versus rejected proposals.
  • Basic authentication—username/password, perhaps an email OTP.

What does this system need?

  • Fast CRUD → BTREE indexes on primary keys and filter columns.
  • Filters and reports → queries with aggregation (SUM, COUNT, GROUP BY), perhaps views.
  • Simple search → full-text search on proposal titles and descriptions, or pg_trgm for searching customer names.
  • Sessions/authentication → a users table plus session or refresh tokens.

All of this fits comfortably into a single Postgres database with:

  • A clear relational schema.
  • A few indexes planned based on real queries.
  • Some full-text or trigram search if needed.

None of these needs, by default, requires you to deploy Redis, Elasticsearch, or a vector database on day one.


3. Replacing the “Redis + Elastic + Vector Database” Trio with Postgres—for Now

Let us look at three classic cases where teams tend to introduce new technologies too early—and how Postgres can handle much of the workload before you need to add complexity.

The point is not to say that Postgres is better than these tools, but to show how far it can go during an MVP phase.


3.1. When You “Think” You Need Redis

Typical cases where someone shouts “Redis!” during MVP planning include:

  • Read caching for frequently accessed endpoints, such as /me or a product list.
  • Centralized user sessions.
  • Rate limiting to prevent API abuse.

These use cases make sense in larger systems, but in an MVP the problem often is not there yet.

What you can do with Postgres alone

  1. “Implicit” caching through indexes and good queries

In many cases, the problem is not “I need caching,” but rather:

  • There is no index on the filtered column.
  • The query runs SELECT * against a huge table.
  • Lists have no pagination.

The combination of:

  • The right indexes—BTREE on filtered columns, GIN on JSONB when necessary.
  • A focused query that selects only the required columns.
  • Proper pagination.

already reduces response times considerably, to the point where an external cache is not a priority at the beginning.

  1. User sessions in Postgres

Instead of storing sessions in Redis, you can:

  • Create a sessions table with:
  • user_id.
  • A token or refresh token.
  • Small pieces of data in JSONB, such as the user agent and IP address.
  • created_at and expires_at.

Or, more simply, use JWTs with a short lifetime and store only refresh tokens in the database. For an MVP, the scale is usually low enough for this to be sufficient for quite a while.

  1. Rate limiting with lightweight tables

You can create an api_usage table with:

  • user_id.
  • endpoint or an operation key.
  • window_start, such as the beginning of the current minute.
  • count.

With a composite index on (user_id, endpoint, window_start), you can apply a limit per user and endpoint for each time window. This is not as efficient as Redis at extremely high scale, but it works well for MVPs and systems with low to moderate traffic.

Practical limits: when Redis starts to make sense

On the other hand, insisting on using Postgres for everything also has limits. Redis starts to make sense when:

  • The Postgres instance is struggling with very frequent repeated reads.
  • Network latency must be extremely low with a high request volume.
  • Traffic spikes are difficult to absorb with Postgres alone, even after optimizing indexes and queries.

In these cases, Redis for hot caching or more aggressive rate limiting is a useful complement. The difference is starting simple and introducing Redis when the problem is clear, rather than doing so out of habit.


3.2. When You “Think” You Need Elasticsearch

Another common scene: an MVP with half a dozen screens already has an Elasticsearch cluster because “we will need powerful search.”

Typical arguments include:

  • “We need Google-style autocomplete.”
  • “Advanced filters everywhere.”
  • “Sophisticated relevance-based search.”

Sometimes that makes sense, but for most MVPs, it is still too early.

What Postgres provides natively for search

  1. Full-text search (tsvector / tsquery)

You can:

  • Create a search_vector column of type tsvector.
  • Populate it from the title, description, and content.
  • Create a GIN index on search_vector.
  • Run queries with to_tsquery or plainto_tsquery.

This lets you:

  • Search for terms.
  • Use stemming—finding “running” when searching for “run,” for example.
  • Rank results with ts_rank.

  • pg_trgm for similarity search

With the pg_trgm extension, you can:

  • Make LIKE queries more efficient.
  • Implement “similar to” or fuzzy search.
  • Build simple autocomplete by prefix or similarity.

  • Well-used GIN/GiST indexes

Combined with tsvector or pg_trgm, these indexes can significantly improve the response time of searches and filters without leaving Postgres or operating a separate cluster.

Example: searching products or blog posts

Imagine a product catalog with:

  • Name.
  • Description.
  • Tags.

You can:

  • Create a search_vector column by concatenating the name, description, and tags and converting them to tsvector.
  • Index it with GIN.
  • Run queries that:
  • Filter by category and price.
  • Search for a text term in search_vector.
  • Sort by basic relevance ranking or by date.

For an MVP, this handles most catalog or content search use cases well.

Practical limits: when Elasticsearch shines

Elasticsearch starts to justify its cost when:

  • You have many documents and complex relevance-based queries.
  • You need facets and more sophisticated aggregations at scale.
  • You require a distributed cluster with high availability specifically for search.
  • You use advanced ranking features, synonyms, boosting, ingest pipelines, and so on.

Until then, Only Postgres for MVPs with full-text search and pg_trgm covers a significant share of use cases without forcing you to operate another critical component.


3.3. When You “Think” You Need a Vector Database

In the post-ChatGPT world, the hype has shifted:

  • “Our MVP needs generative AI.”
  • “We are going to build RAG—Retrieval-Augmented Generation—from day one.”
  • “I deployed a dedicated vector database, so now I am ready for the future.”

For many AI MVPs, this is more complexity than necessary.

What already exists in the Postgres ecosystem

Postgres now has extensions such as:

  • pgvector: adds a vector data type and indexes for similarity search—cosine distance, L2, and others.

In practice, you can:

  • Have a documents table with:
  • id, title, and content as regular columns.
  • embedding as a vector column provided by pgvector.
  • Insert the content and embedding generated by an external model.
  • Run vector similarity queries to retrieve relevant documents.

With this, you can build a basic RAG system using only Postgres and pgvector, which is enough for many proofs of concept and pilots.

Why this is enough for many AI MVPs

Many AI MVPs:

  • Have few documents—hundreds or a few thousand.
  • Have a low query frequency—a demo, proof of concept, or paid pilot.
  • Do not require ultra-low latency.

Under these conditions, Postgres with pgvector performs well:

  • Fewer components to administer.
  • Lower infrastructure costs.
  • Easier for the team to maintain and debug.

Practical limits: when a dedicated vector database is justified

Dedicated vector databases start to make sense when:

  • You have large datasets—on the order of millions of vectors.
  • You need very low latency for frequent vector queries.
  • You want advanced partitioning, index caching, and replication features specific to this type of data.

Reaching this point is usually a great sign: it means your AI product has moved beyond the MVP phase and reached a different level. But you do not need to start there.


4. How Far Does Postgres Go? Signs That Everything Is Still Fine

Simple monitoring dashboard showing response time, database connections, and table size.
Simple monitoring dashboard showing response time, database connections, and table size.

How do you know whether Only Postgres for MVPs is still a healthy choice for your context?

Checklist: “Everything is fine—keep using Only Postgres”

Some signs that things are under control:

  • Average latency is acceptable under realistic load
  • The most common requests respond within a time appropriate for your use case.
  • The database is not an obvious bottleneck
  • CPU is usable, I/O is within normal levels, and locks are under control.
  • Your domain still fits into a clear schema
  • It has not become a tangle of tables and JSONB that nobody understands.
  • Your team understands most of what is running
  • The main queries are readable.
  • Indexes are not a black box that nobody knows how to justify.

Simple metrics to track

Without building a huge observability stack, you can already get useful signals by looking at:

  • Average execution time of the most common queries
  • Track the 10–20 most frequently executed queries: are they stable or getting worse?
  • Active connections versus the limit
  • Check whether you are approaching max_connections or whether the connection pool is poorly configured.
  • Growth of the main tables
  • Are tables growing too quickly? Is it time to consider partitioning or cold storage?

Tools such as pg_stat_statements and the slow query log already provide a lot of value without requiring a complex ecosystem around them.

Pitfall: premature optimization

Common mistakes in this discussion include:

  • Adding caching everywhere before measuring.
  • Introducing a queue, Redis, and Elastic “because it is more professional.”
  • Estimating high-scale problems without having traffic that justifies the concern.

There is no bonus for the number of technologies in an MVP. In general, this increases technical debt and failure points without providing a real benefit during the early phase.


5. When “Only Postgres” Actually Starts to Hurt

It is also important to acknowledge the other side: Postgres cannot handle everything forever. How can you tell that you are reaching the healthy limit of an Only Postgres for MVPs model?

Clear signs that it is time to add other components

  1. Postgres became a bottleneck even after basic optimization

You have already:

  • Adjusted indexes based on real queries.
  • Reviewed the most frequently used queries.
  • Fixed N+1 queries and unnecessary access.
  • Adjusted basic memory and connection settings.

Even so:

  • Latency remains high under real usage.
  • CPU and I/O are constantly near their limits.
  • Lock contention is frequent.

  • Very different access patterns are competing for the same database

A common example is:

  • Transactional workload—application CRUD—coexisting with:
  • Heavy reports.
  • Intensive batch processes.
  • BI analytics querying the production database directly.

This often calls for:

  • Dedicated read replicas for reports.
  • A separate data warehouse.
  • Queues or events to feed other databases.

  • Latency or availability requirements that tuning alone cannot meet

If you need:

  • A very strict millisecond-level SLA.
  • Extremely high write concurrency.
  • Complex geographic distribution.

…it may be time to:

  • Add caching with Redis.
  • Use queueing mechanisms.
  • Split responsibilities across more than one specialized system.

Examples of scenarios where moving beyond Only Postgres makes sense

Some examples include:

  • Adding Redis for distributed caching when:
  • You have extremely demanding read endpoints accessed at high frequency.
  • The response can be reused for many users.

  • Using a queue—Kafka or RabbitMQ—when:

  • Asynchronous processes are heavy and affect the user experience.
  • You need to scale workers independently and support structured reprocessing.

  • Introducing Elasticsearch when:

  • You have many documents and need advanced search, heavy facets, and finely adjustable relevance.
  • Search is important enough to justify a dedicated cluster.

In these scenarios, Postgres remains part of the solution, while specialized tools address specific demands that the database alone cannot handle comfortably.


6. A Practical Strategy: How to Start with Only Postgres Without Getting Trapped

Timeline showing an architecture evolving from an app with PostgreSQL to one that later adds Redis and other components.
Timeline showing an architecture evolving from an app with PostgreSQL to one that later adds Redis and other components.

A legitimate concern is: “If I start with Only Postgres for MVPs, will I lock myself into a path with no way back?”

In practice, this depends much more on how you organize your code than on the technology itself.

Modeling with future evolution in mind

Some practical ideas:

  • Separate application layers
  • Use something like ports and adapters, hexagonal architecture, clean architecture, or at least an infra module that isolates data access.
  • Avoid scattering raw SQL throughout the codebase.

  • Avoid depending on highly specific details too early

  • If you know you may migrate from Postgres full-text search to Elastic in the future, hide that behind a search interface.
  • The same applies to caching: implement a cache interface that talks to Postgres today and can talk to Redis tomorrow.

This lets you start with Only Postgres for MVPs without blocking future evolution.

Example: designing cache and search interfaces

  1. Cache interface

You might have something like:

  • CacheService.get(key)
  • CacheService.set(key, value, ttl)

At the beginning:

  • Implement CacheService using a cache_entries table in Postgres.

In the future, if necessary:

  • Implement a new version of CacheService using Redis.
  • The rest of the system does not need to know that the backend changed.

  • Search service

Create something like:

  • SearchService.searchProducts(query, filters)
  • SearchService.searchArticles(query)

At first:

  • Implement it using full-text search—tsvector—and pg_trgm in Postgres.

If you need to scale later:

  • Implement another SearchService that calls Elasticsearch.
  • Migrate the data gradually, switching the implementation with a feature flag if necessary.

Good practices for using Postgres in this context

A few precautions help sustain this strategy:

  • Monitor from the beginning
  • Enable the slow query log.
  • Use pg_stat_statements to understand what is actually being executed.

  • Create indexes incrementally

  • Avoid creating indexes on everything “just in case.”
  • Add indexes as real queries appear and are measured.

  • Be careful with obscure extensions

  • pg_trgm, pgvector, and the full-text search engine are relatively well established.
  • Very unusual extensions can make version upgrades or migrations more difficult.

How to communicate this strategy to the team and stakeholders

Finally, there is the alignment work:

  • For the technical team:
  • “We will start simple with Only Postgres for MVPs, but the architecture is designed to support adding or replacing services later.”
  • Show how interfaces for caching, search, and queues allow infrastructure details to change without rewriting the domain.

  • For stakeholders—product, business, and leadership:

  • Explain the cost of carrying technologies that may never actually be used.
  • Emphasize that adding Redis, Elastic, or a vector database is not forbidden—it is simply a decision we want to make based on data, when the pain appears.

7. Conclusion: The Power of Delaying Complexity

The central point of this article is not that “Postgres is the answer to everything.” It is something more pragmatic:

Postgres is an excellent “safe default” for starting most MVPs.

It offers:

  • Modern features—JSONB, full-text search, and extensions such as pg_trgm and pgvector.
  • Relatively simple operations.
  • A known path for evolution—replicas, partitioning, and offloading to other tools.

The suggested strategy is:

  • Use Only Postgres for MVPs as the default.
  • Measure performance and track a few simple metrics.
  • Optimize the basics—indexes, queries, and configuration.
  • Then add Redis, Elasticsearch, a dedicated vector database, or queues when the problems are clear and measurable.

PostgreSQL can solve many common needs—such as simple caching, basic queues, text search, and even early AI use cases with extensions—but these solutions do not replace specialized tools in every scenario. At some point, it makes sense to bring in dedicated systems to scale specific types of workloads more effectively.

Healthy architecture is not the architecture with the most logos on the diagram. It is the one that grows with the product—neither before nor after it needs to.

If you have experienced technology overload in an MVP, consider sharing your experience with other software developers. These stories help prevent the next project from starting with more infrastructure than users.

  • Join the SCCB community — https://instagram.com/software_craftsmanship
  • See upcoming events — https://instagram.com/software_craftsmanship

Next Steps

If you want to put this approach into practice on your next project:

  1. Make Postgres the explicit default
  2. Document it in the project README: “We will start with Only Postgres; Redis, Elastic, and other tools will be added only if metrics X/Y/Z show a problem.”

  3. Map infrastructure interfaces early

  4. Identify where abstractions make sense: caching, search, and queues/events.
  5. The goal is not to create layers for their own sake, but to avoid tight coupling to a specific solution.

  6. Configure the minimum observability required

  7. Enable the slow query log and pg_stat_statements.
  8. Create a simple dashboard to track average query time and connections.

  9. Review your current architecture

  10. If your low-traffic MVP already has Redis, Elastic, or a vector database, ask:

    • “Which parts are actually being used?”
    • “What could be handled by Postgres again without significant pain?”
  11. Share lessons with the team

  12. Use this discussion to align expectations: neither 8—an indexless chaotic monolith—nor 80—a distributed cluster with no users.

Did you enjoy this article?

Share it with your friends and help spread knowledge!