Skip to main content

SynthQL

The type-safe HTTP client for your PostgreSQL database.

What is SynthQL

SynthQL is a full stack HTTP client for your PostgreSQL database. It lets you declaratively describe your React component's data dependencies.

With SynthQL you can focus on building great products instead of spending time thinking how to most efficiently fetch data into your components.

SynthQL reads your PostgreSQL database schema and generates types so you get type safety end to end.

const q = from('movies')
.columns('id', 'title', 'release_date')
.filter({ id: 1 })
.take(10);

// Execute the query
const { data: movies } = useSynthql(q);

// movies is now an array of movies with id, title and release_date
// properties
console.log(movies[0].id)

Why SynthQL?

End-to-end type safety

Generate types from your schema with a single command. Run in on your CI to ensure types are always up to date.

Read more
npx @synthql/cli generate --url $DATABASE_URL

Composable query language

Build complex queries by composing smaller queries together. The SynthQL query language is designed for easy composition and re-use.

const findPetsByOwner = (owner) =>
from('pets')
.filter({ owner })
.many();

const findPersonById = (id) => {
const pets = findPetsByOwner(id)
return from('people')
.filter({ id })
.include({ pets })
.one()
}

Built-in pagination & streaming

Pagination in SynthQL just works! You don't need to do anything special to enable it!

Read more

const query = from('users')
.filter({age: {gt:18}})
.take(100) // set the size of the page

const {data, fetchNextPage} = useSynthql(query)

Lazy queries

As queries become bigger, latency also grows. Lazy queries help you split large object graphs to optimize page load. In the following example, we use a lazy query to load a store and its products separately. This means the store can load quickly and the products can load in the background. This is especially useful when the products are not immediately visible on the page.

Read more

const products = from('products')
.column('id', 'name', 'price')
.filter({
product_id: { in: col('store.product_ids') }
})
.lazy()
.many()

const query = from('store')
.column('id', 'name')
.filter({ id })
.include({
products
})

// Over the network, this results in two JSON lines
[{ id: "store 1", name: "Fnacy store", products: { status: 'pending' } }]
[{ id: "store 1", name: "Fancy store", products: { status: "done", data: [...] } }]

Security

SynthQL offers a number of security features to help you secure your application. This includes built-in authentication, query whitelisting, and more.

Read more

const findPetsByOwner = (ownerId) => {
return from('pets')
.column('name','id')
.filter({ ownerId })
.requires('pets:read')
.many()
}

const findPersonByIds = (ids) => {
return from('people')
.column('first_name','last_name')
.requires('person:read')
.filter({id:{in:ids}})
.include({
films: findPetsByOwner(col('people.id'))
})
.many()
}

Custom query providers

Not all data comes from the database. Use custom providers to join your DB tables with data from 3rd party APIs using a predictable performance model.

Read more

const findFilmsWithRatings = () => {
const ratings = from('rotten_tomatoes_ratings')
.filter({
year:col('film.year')
})
.many()

return from('films')
.filter({ year: 1965 })
.include({ ratings })
.many()
}

Ready to get started?