Main article: Writings by Jiru Gutema.
Vector databases sound complex, but the core idea is surprisingly simple: AI models only convert text into numerical vectors (embeddings), while the database handles storage and search. This article breaks down how semantic search actually works in real applications, from generating embeddings asynchronously to using PostgreSQL + pgvector for fast, meaningful results. You'll learn why background processing matters, when to use embeddings (and when not to), and how this architecture powers practical AI features like intelligent CRM search.
When developers first hear about vector databases, embeddings, and AI-powered search, the architecture can feel surprisingly confusing. Explanations often jump straight into high-dimensional vectors, cosine similarity, nearest neighbor algorithms, and other concepts that make the whole thing sound more complicated than it actually is.
The reality is much simpler.
A vector database is not some magical AI system that understands language on its own. It is still a database. The AI model is not continuously reading your data or answering questions from your tables. Instead, the AI model performs one very specific task: it converts text into numbers. Once that conversion is complete, the database takes over and does what databases do best—store and retrieve information efficiently.
Understanding this separation of responsibilities is the key to understanding modern AI search systems.
Imagine you're building a CRM system. Your users create support tickets, meeting notes, emails, and customer interactions every day.
One support ticket contains the text:
"Customer cannot log in after password reset."
Several weeks later, another support agent searches for:
"I can't access my account."
From a human perspective, these two sentences clearly describe the same problem. However, a traditional SQL search engine sees them as completely different collections of words.
A query such as:
SELECT * FROM tickets WHERE description ILIKE '%account%';
will not find the original ticket because the word "account" never appears in the stored text.
This limitation becomes increasingly painful as systems accumulate large amounts of unstructured content. Support tickets, emails, notes, documents, and chat conversations rarely use identical wording, even when discussing the same topic.
What organizations actually want is semantic search — the ability to search by meaning rather than by exact keywords.
This is where embeddings enter the picture.
An embedding is simply a numerical representation of text generated by an AI model.
Suppose we take the sentence:
"Customer cannot log in after password reset."
An embedding model might convert it into something like:
[0.12, -0.34, 0.89, 0.22, ...]
The actual vector is typically much larger — often containing hundreds or even thousands of dimensions.
The important thing to understand is that these numbers encode meaning. Sentences with similar meanings tend to produce vectors that are close to one another in vector space.
For example:
...will generate vectors that are much closer together than vectors generated from unrelated sentences such as:
"Payment processing completed successfully."
The embedding model has essentially translated human language into mathematics. Once text becomes mathematics, databases can perform similarity calculations.
One of the most common misconceptions is that vector databases somehow generate embeddings themselves. They do not.
Embeddings are generated by specialized AI models provided by services such as OpenAI, Azure OpenAI, Cohere, Google, Voyage AI, or self-hosted models running through Ollama or Hugging Face.
For example, an application might send text to OpenAI’s embedding API:
const response = await openai.embeddings.create({ model: "text-embedding-3-small", input: ticketText });
The API returns a vector:
[ 0.023, -0.117, 0.442, ... ]
The application then stores this vector alongside the original record. At this point, the AI model’s job is complete. The database now owns the search problem.
Many developers initially assume that every save operation must go through AI before reaching the database. Technically that can work, but it is usually a bad idea.
Consider a support ticket creation workflow.
The naïve implementation:
Create Ticket ↓ Call OpenAI ↓ Generate Embedding ↓ Save Ticket ↓ Return Success
This introduces latency, fragility, and poor user experience.
The better approach:
Create Ticket ↓ Save Ticket ↓ Publish Job ↓ Return Success
Then, in the background:
Background Worker ↓ Generate Embedding ↓ Update Record
This design is especially important in modern serverless environments like Vercel. Serverless functions are designed to handle requests quickly and then terminate — they are not meant for long-running AI jobs.
A better architecture separates responsibilities:
Next.js API ↓ PostgreSQL ↓ Queue ↓ Embedding Worker ↓ PostgreSQL
When a ticket is created, the API stores the ticket and publishes a message. The worker eventually consumes the message, generates the embedding, and updates the record. This provides retries, fault tolerance, and scalability without slowing down the user experience.
Once embeddings exist, PostgreSQL (with the pgvector extension) can search them efficiently.
The table might look like this:
CREATE TABLE tickets ( id SERIAL PRIMARY KEY, description TEXT, embedding VECTOR(1536) );
When a user searches "I can't access my account," the application:
Search Query ↓ Embedding Model ↓ Query Vector ↓ PostgreSQL Vector Search ↓ Most Similar Records
Important: PostgreSQL performs the search. The AI model only converts text into vectors.
Imagine a CRM containing years of support history. A support agent receives a new issue:
"Payment requests are timing out during checkout."
The system generates an embedding and searches the vector index, returning records such as:
None of these tickets use identical wording, yet they describe similar situations. The support agent immediately sees previous investigations and resolutions.
This is where vector search creates real business value.
Another common misconception is that every table should become vector-enabled. In reality, most tables never need embeddings.
Users, roles, permissions, organizations, and configuration data are typically queried using exact matches or relational joins.
Embeddings make sense for content where semantic understanding adds value:
Applying embeddings everywhere usually increases costs without delivering meaningful benefits.
Vector databases are often presented as revolutionary new systems that replace traditional databases. In practice, they are usually an extension of existing databases.
The AI model converts information into vectors.
The database stores those vectors.
Similarity algorithms find related records.
The application uses those results to power intelligent experiences.
What appears magical to users is actually a collaboration between three very ordinary components: the application, the embedding model, and the database.
Once you understand that separation, the architecture becomes surprisingly straightforward.
The next time someone says they’re building an AI-powered CRM search feature, you can mentally translate it into something much simpler:
Store the data → Generate embeddings → Save the vectors → Let the database find similar records.
Everything else is implementation detail.
Did you find this helpful?