Skip to main content

Quick Start

The best way to learn Vespa is to build something. In this chapter, we will deploy your first Vespa application, feed some data, and run queries. This hands-on walkthrough gives you a feel for how Vespa works and introduces the basic workflow you will use throughout this course.

We will use the album recommendation sample application. This example demonstrates core Vespa concepts including schemas, document feeding, and querying with custom ranking. By the end of this chapter, you will have a working Vespa application running on your machine.

Prerequisites

Before you begin, make sure you have completed the setup from the previous chapter. You need:

A Docker or Podman installation running on your machine. You can verify this by running docker --version or podman --version and seeing version information.

The Vespa CLI installed. You can check this with vespa version. If you don't have it yet, refer back to the Setting up Vespa chapter for installation instructions.

At least 4 GB of RAM allocated to your container runtime. This ensures Vespa has enough resources to run properly.

Configuring the CLI for Local Development

First, tell the Vespa CLI that you want to work with a local instance rather than Vespa Cloud. Run this command:

vespa config set target local

This configuration persists across sessions, so you only need to do it once. The CLI will now send deployments and queries to localhost instead of the cloud.

Starting Vespa

Now let's start a Vespa container. We covered this in the setup chapter, but here is the command again:

docker run --detach --name vespa --hostname vespa-container \
--publish 8080:8080 --publish 19071:19071 \
vespaengine/vespa

This starts Vespa in the background. Port 8080 is for queries and feeding data. Port 19071 is for deploying applications. The container is named "vespa" so you can easily reference it later.

After running this command, wait a minute or two for Vespa to initialize. You can check the logs to see when it is ready:

docker logs vespa --follow

Watch until you see messages indicating that services have started. Once you see that the config server and container are available, Vespa is ready to receive an application deployment.

Getting the Sample Application

Vespa provides sample applications to help you get started. We will use the album recommendation app, which demonstrates search and simple recommendation features. To get it, run:

vespa clone album-recommendation myapp && cd myapp

This command downloads the sample application into a directory called "myapp" and changes into that directory. The sample includes everything you need: a schema definition, some configuration files, and sample data.

Let's look at what's inside. Run ls and you will see an app directory and a dataset directory. The app directory contains your application package (the schema and configuration). The dataset directory contains JSON documents to feed into Vespa.

Take a look at the schema by opening app/schemas/music.sd. Don't worry about understanding every detail yet, but notice that it defines a document type called "music" with fields for artist, album, year, and category_scores. It also defines ranking profiles that control how results are scored. We will cover schemas in depth in the next module.

Deploying the Application

Now let's deploy this application to your local Vespa instance:

vespa deploy --wait 300 app

The --wait 300 flag tells the CLI to wait up to 300 seconds for the deployment to complete. The app argument points to the directory containing your application package.

When you run this, the CLI packages your application, sends it to the Vespa config server, and waits for the deployment to finish. You will see output indicating the upload progress and then messages about the deployment activating. When it says "Success", your application is deployed and ready to receive data.

What just happened behind the scenes? The config server received your application package, validated the schema, computed the configuration for all nodes, and pushed that configuration out to the running services. The content nodes now know what kind of documents to expect and how to index them. The container nodes know what queries to accept and how to rank results.

Feeding Documents

An application without data is not very useful, so let's feed some documents. The sample includes a file called documents.jsonl (JSONL means JSON Lines, where each line is a complete JSON document). Feed these documents with:

vespa feed dataset/documents.jsonl

The CLI reads each document from the file and sends it to Vespa. You will see progress output showing how many documents have been fed and the rate. The sample has a handful of documents representing music albums. They feed quickly, usually finishing in a second or two.

Each document includes an ID, the artist name, album name, year, and category scores as a tensor with weights for genres like pop, rock, and jazz. As Vespa receives each document, it stores it and updates the indexes. The documents become searchable immediately after they are indexed.

Running Your First Query

Now that you have data in Vespa, let's query it. Start with a simple text search:

vespa query "select * from music where album contains 'head'"

This query searches for albums where the album title contains the word "head". The query language here is called YQL (Vespa Query Language), which looks similar to SQL. We will cover YQL in detail in a later chapter, but for now just understand that this searches the "album" field for documents matching "head".

Look at the results. You should see a JSON response containing matching documents. The response includes the total hit count, the documents themselves with all their fields, and some metadata about the query execution. One of the results might be "A Head Full of Dreams" by Coldplay.

Querying with Ranking

Let's try a more interesting query that uses custom ranking. Run this:

vespa query "select * from music where true" \
"ranking=rank_albums" \
"ranking.features.query(user_profile)={{cat:pop}:0.8}"

This query is more complex. Let's break it down:

The where true clause means match all documents (no filtering). The ranking=rank_albums parameter tells Vespa to use a specific ranking profile defined in the schema called "rank_albums". The ranking.features.query(user_profile) parameter passes a feature to the ranking function. In this case, we are saying the user has a preference for the "pop" category with a weight of 0.8.

The ranking profile combines this user preference with document features to compute a relevance score. Documents in the "pop" category will rank higher than others. Look at the results and notice how they are ordered. The ranking profile is doing personalized ranking based on the user preference you passed in.

This demonstrates one of Vespa's key strengths: you can define sophisticated ranking functions that combine query features, document features, and custom logic. The ranking happens at query time, so you can personalize results for each user without pre-computing scores for every user-document pair.

Retrieving Specific Documents

In addition to searching, you can retrieve documents directly by ID. Try this:

vespa document get id:mynamespace:music::a-head-full-of-dreams

This fetches a specific document by its ID. Vespa returns the complete document with all fields. Direct document retrieval is useful when you know exactly which document you want, like showing a product detail page after a user clicks a search result.

You can also use the visit API to dump all documents:

vespa visit

This streams out all documents in your Vespa instance. For production systems with millions of documents, you would use visit with filters and pagination. For our small sample, it just shows all the music documents.

What You Have Learned

In this quick start, you went through the complete cycle of working with Vespa. You deployed an application with a schema defining document structure and ranking profiles. You fed documents into the system. You ran queries using text search and custom ranking. You retrieved specific documents by ID.

This workflow is what you will use throughout this course and when building real applications. The schemas will get more complex, the queries will become more sophisticated, and the ranking functions will incorporate machine learning models, but the basic pattern stays the same: define your schema, deploy, feed data, query.

Cleaning Up

When you are done experimenting, you can stop and remove the Vespa container:

docker rm -f vespa

This removes the container and frees up resources. The next time you want to work with Vespa, you will start a fresh container. For development and learning, this clean slate approach works well. For production, you would configure persistent storage so data survives container restarts.

Next Steps

Now that you have seen Vespa in action, the next chapter will guide you through setting up your own development environment for the hands-on labs throughout this course. Then we will dive deeper into schemas, document structure, and how to model your data for Vespa.

For more sample applications and tutorials, visit the Vespa sample apps repository and the Vespa documentation tutorials.