arrow_backBlog

Vantage Deep Dive: Thinking in Sets

An ORM hands you records one at a time. Vantage operates with Data Sets in real-time.

Romans Malinovskis

6 min read

Sunrise over the Hook of Holland ferry terminal: loading ramps reach out from the quay to the water, with a row of wind turbines on the far bank.

Sunrise at the Hook of Holland ferry terminal, after the overnight crossing from Harwich.

In the previous deep dive I left a question mark between Cart and Item. I promised that a relation is easy to change later. Before we get to how relations are declared, I want to talk about the idea underneath them, because it is the reason Vantage looks the way it does.

In Vantage you work with Sets of Records most of the time.

How simple code gets lost๐Ÿ”—

A client runs a web shop and wants an admin dashboard that shows the total amount sitting in all open carts. Most software reaches the database through a database abstraction layer, and in practice that means picking one of two teams:

Requirement

Admin dashboard: total amount across all open carts.

Team ORM

total = 0
for cart in Cart.filter(status="open"):
    for line in cart.items:
        total += line.amount

4 lines · loads every cart

Team SQL

SELECT SUM(i.amount)
FROM cart c
JOIN cart_item i ON i.cart_id = c.id
WHERE c.status = 'open'

4 lines · knows the schema

New requirement

Keep the dashboard live. Next quarter, carts move to MongoDB.

Both teams: rewrite

  • cart service
  • outbox
  • Kafka
  • consumer
  • projection
  • read model
  • WebSocket

plus idempotency keys, retries, replays and projection rebuilds

months of work for a team · TCOTCO Total cost of ownership: everything a system costs over its whole life, not just to build it, including running, maintaining, staffing and changing it.Read the docs โ†’ for life

I gave this requirement to AI agents. Each got the first ticket and chose a team: half wrote the SQL, half used their ORM. When I added that the code mustn't depend on the database, the agent wrote the loop. Then I added the second ticket, and every agent gave the same answer: the pipeline above, plus a view that runs behind the data. Their sketches fit on a page. Building and running each box takes a team months, which is why companies at this stage employ hundreds of engineers.

That is how most apps grow. You start with SQL or an ORM. When you have to scale, you rewrite and bring in a wide range of tools. Along the way the simple, readable code is lost in implementation detail, and the core of the app becomes hard to maintain.

Define it now, don't rewrite later๐Ÿ”—

Vantage takes the other road. Business code doesn't assume SQL and doesn't fetch records: it describes sets of records and traverses from set to set. SQL works in sets too, but SQL is implementation: it names tables, joins and an engine. A set is business code: it says which records you mean. In Vantage a data set is a VistaVista A universal handle on one table from any data source. It knows the columns, their types and what the source can do, so a generic grid or form can work with it without knowing your database.Read the blog post โ†’Read the docs โ†’, the primitive from the previous deep dive, detached from how and where the data is stored. The code stays easy to read, and Vantage handles the implementation details, which you can still customise where you need to.

Requirement

Admin dashboard: total amount across all open carts.

What you write

# table/cart.yaml
# Defines the Vista (a data set): columns, conditions and references.
datasource: shop_pg
columns:
  id: { type: string, flags: [id] }
  user: { type: string, references: user }
  status: { type: string, enum: [open, ordered] }
references:
  items: { table: cart_item, kind: has_many, foreign_key: cart }
let report_vista = table("cart")
    .where("status", "open").ref("items");

Each step returns a new VistaVista A universal handle on one table from any data source. It knows the columns, their types and what the source can do, so a generic grid or form can work with it without knowing your database.Read the blog post โ†’Read the docs โ†’. Bind report_vista to a widget, and the widget totals the amount.

You get, without writing it:

  • WebSocket API
  • live updates
  • REST and MCP
  • typed TypeScript client
  • sessions and scope
  • ACL and policies

a dozen lines of YAML and Rhai

New requirement

Keep the dashboard live. Next quarter, carts move to MongoDB.

What you change

# table/cart.yaml
- datasource: shop_pg
+ datasource: shop_mongo

one line · business code unchanged

Live updates are among those details. Each data source reports its own changes: PostgreSQL through LISTEN/NOTIFY, MongoDB through change streams, and SurrealDB through LIVE SELECT, which can even push the totals of a pre-computed view as the rows under it change. Vantage turns them into updates over its WebSocket API. The event pipeline from the first story still exists, but it is part of Vantage: it runs inside Vantage Server, and nobody on your team has to manage it. The Enterprise edition goes a step further and plugs into the event architecture a company already runs, such as CDC with Debezium, scaling horizontally with it.

Moving the data to MongoDB takes one line because traversal doesn't depend on the database: each ref() turns one VistaVista A universal handle on one table from any data source. It knows the columns, their types and what the source can do, so a generic grid or form can work with it without knowing your database.Read the blog post โ†’Read the docs โ†’ into the next, whether or not both tables share a database.

If you prefer to write Rust, Vantage offers all the base components as MIT-licensed open source: Vista, Factory, Diorama and Scenery. They are what Vantage ServerVantage Server Serves the same YAML and Rhai project as an API, with live WebSocket updates, REST, MCP, sessions and access rules, for web apps and other clients. and Vantage UIVantage UI The desktop app builder: you and your LLM describe tables, pages and actions in YAML and Rhai, and it turns them into a working app.Read the docs โ†’ run on.

Conclusion๐Ÿ”—

Follow the same app through four requirements. Each colour is code written at a different time, so a new colour means the code before it was rewritten.

Launchtotal across carts New databasecart data to MongoDB Live viewadmin dashboard Load grows10× the traffic Typical stack ORM or SQL queries, sync jobs event pipeline caches, replicas Vantage business code written at launch

~10×faster to build an app than with an LLM alone, in our tests

1 lineto move a table to another database

0rewrites of business code across all four

Vantage pursues an architectural goal: keep business code apart from implementation. Business code works with VistasVista A universal handle on one table from any data source. It knows the columns, their types and what the source can do, so a generic grid or form can work with it without knowing your database.Read the blog post โ†’Read the docs โ†’: which records you mean and how they relate. Storage, queries, live updates and scaling are implementation, and Vantage implements them once, beneath every table. That is where the speed comes from, and it is why the business code doesn't need replacing as the system grows.

Most of the cost of a business system comes after the first version. In companies where hundreds of engineers maintain a shared codebase, it is the rewrites and the infrastructure that follow every new requirement. Code written for Vantage is long-term code: it scales with the system instead of being replaced by it.

โ† All posts