🚀 White Paper: Fauna Architectural Overview - A distributed document-relational database delivered as a cloud API.
Download free
Fauna logo
Product
Solutions
Pricing
Resources
Company
Log InContact usStart for free
Fauna logo
Pricing
Customers
Log InContact usStart for free
© 0 Fauna, Inc. All Rights Reserved.

New!

FQL: A relational database language with the flexibility of documents

A strongly-typed language that combines the ability to express declarative relational queries and functional business logic in strongly consistent transactions.

START FOR FREEVIEW DOCUMENTATION

“With FQL, Fauna marries simplicity with power. Now, we can do aggregation and projection more effortlessly than in MongoDB.”

Matt Haman

CTO, Rownd

let currentUser = Query.identity()

Order.where(.customer == currentUser && .product.type == "Computers")
  .order(desc(.date))
  .take(10) {
    user:    .customer.name,
    ordered: .date,
    item:    .product.name,
    price:   .product.price
  }

EXAMPLE. How to get a logged-in customer’s recent orders in a given product category.

Intuitive. Familiar. Powerful.

FQL draws inspiration from programming languages like TypeScript and Python, making it familiar and easy to adopt. Context-specific suggestions from developer tools, FQL's robust type checking, and its regular syntax help you quickly build correct queries, while its controls over query execution ensure consistent performance as your application grows.

1Product.where(.type == "Book" && .quantity > 0)
2  .order(type.price)
3  .take(10) 
4  {
5    name, price, quantity 
6  };
7    
{
  data: [
    {
      name: "The Doors of Stone",
      price: 20.6,
      quantity: 100
    }
  ]
}
1Product.all().map(p => {
2  name: p.name,
3  quantity: p.quantity,
4  totalOrderCount: Order.byProduct(p).count(),
5  recentOrders:
6Order.byProduct(p).order(desc(.date)).take(3) {
7    date,
8    customer
9  }
10});
{
  data: [
    {
      name: "Allure Auto CM 40 Car Mat Hyundai Elantra",
      quantity: 26,
      totalOrderCount: 2,
      recentOrders: {
        data: [
          {
            date: "2009-09-23",
            customer: {
              name: "Janine Labrune",
              address: {
              ...

The data you want — and nothing more

Eliminate over-fetching, minimize round-trips, and simplify client-side logic. FQL's concise, GraphQL-inspired projection syntax combined with its JSON-like, flexible result format lets you structure your query result exactly how your application expects it, without the additional overhead of an ORM.

Efficient transactions as requests

FQL is a full-fledged language capable of directly expressing complex control flow and conditional logic. Its simple transaction-as-request model solves the problem of inefficient, multi-stage transactions and further enables stateful operations for serverless and edge compute environments. All while avoiding the need to manage expensive, stateful connections.

1let customer = Customer.byUsername("Alice Smith").first()!
2let product =  Product.byName("The Doors of Stone").first()!
3if(product.quantity == 0) {
4  abort({ message: "not in stock", item: product })
5}
6product.update({ quantity: product.quantity - 1 })
7Order.create({ 
8  date: Date.today(),
9  product: product,
10  customer: customer
11})
{
  id: "373707981810827329",
  coll: Order,
  ts: Time("2023-08-21T21:49:14.090Z"),
  date: Date("2023-08-21"),
  product: Product.byId("373707912915189825"),
  customer: Customer.byId("357949884875145300")
}
1collection Customer {
2  index byUsername { terms [.username] };
3  unique [.username];
4}
5
6function createOrder(customer: 
7Customer, product: Product): Order {
8  if (product.quantity > 0) {
9    abort({ message: "not in stock", item: product })
10  }
11
12  product.update({ quantity: product.quantity - 1 })
13  Order.create({ 
14    date: Date.today(),
15    product: product,
16    customer: customer
17  })
18}

Manage your database as code

Fauna's schema language is the source code for your data model. Define your application's database resources--collections, constraints, access controls, and user-defined functions--in one place, and leverage standard source-driven workflows to treat your database as just another deployment target. Let Fauna safely apply the minimal changes necessary as schema evolves.

Dynamically composable, yet secure.

FQL's drivers offer template-based query interpolation built upon a secure wire protocol that prevents injection vulnerabilities. Leverage FQL's uniform, composable structure to dynamically generate sophisticated queries based on application input.

1const custId = 
2 window.sessionStorage.getItem("customerId");
3const custLookup = fql`Customer.byId($custId)!`;
4const prodLookup = 
5fql`Product.byName($productName).first()`;
6
7const result = await client.query(fql`
8  if ($prodLookup != null) {
9    createOrder($custLookup, prodLookup)
10  } else {
11    abort({ message: "product not found" })
12  }
13`);

Purpose-built for application development

JOINS (SQL vs FQL)

Unlike SQL, FQL automatically resolves relations providing concise aliasing and projection.

// SQL

SELECT customer.NAME AS user,
       orderDate     AS ordered,
       product.NAME  AS item,
       product.price AS price
FROM   "Order" as o 
       JOIN customer
         ON o.customerId = customer.customerId
       JOIN product
         ON o.productId = product.productId
WHERE  Product.type = 'Computers'
ORDER BY orderDate DESC;
// FQL

Order.where(.product.type == "Computers")
  .order(desc(.orderDate)) {
    user:    .customer.name,
    ordered: .orderDate,
    item:    .product.name,
    price:   .product.price
  }

COMPOSABILITY (SQL vs FQL)

No verbose SQL joins: FQL uses iterators, method chaining, and inline projection...

// SQL

WITH productCTE AS (
  SELECT
    p.productId,
    name,
    COUNT(*) AS sold
  FROM Product AS p
  JOIN "Order" AS o
    ON p.productId = o.productId
  WHERE p.type = 'Computers'
  GROUP BY p.productId
)

SELECT
  p.name,
  p.sold,
  o.date,
  c.address_country AS country,
  r.stars,
  r.message
FROM productCTE as p
JOIN "Order" as o on p.productId = o.productId
JOIN Customer as c on c.customerId = o.customerId
JOIN Review as r on p.productId = r.productId
ORDER BY p.name, o.date DESC, r.stars DESC;
// FQL

Product.byType("Computers").map(p => {
  let totalSold = Order.byProduct(p).count()
  let recentOrders = Order.byProduct(p)
    .order(desc(.date))
    .take(3)
    .toArray()
  
  let reviews = Review.byProduct(p)
    .order(desc(.stars))
    .take(3)
    .toArray()

  {
    name: p.name,
    sold: totalSold,
    recentOrders: recentOrders {
      date,
      country: .customer.address.country
    },
    reviews: reviews {
      stars,
      message
    }
  }
})

... SQL’s joins often contain redundant data; FQL’s result sets adhere to your domain model.

name         | sold | date         | country | stars | message                        
-------------------------------------------------------------------------------------
iMac         | 5    | 2023-01-20   | France  | 5     | Beautiful display!   
iMac         | 5    | 2023-01-20   | France  | 4     | Fast computer
iMac         | 5    | 2023-01-20   | France  | 3     | Mouse could be better
iMac         | 5    | 2023-02-15   | USA     | 5     | Beautiful display!
iMac         | 5    | 2023-02-15   | USA     | 4     | Fast computer
iMac         | 5    | 2023-02-15   | USA     | 3     | Mouse could be better
iMac         | 5    | 2023-03-01   | Japan   | 5     | Beautiful display!
iMac         | 5    | 2023-03-01   | Japan   | 4     | Fast computer
iMac         | 5    | 2023-03-01   | Japan   | 3     | Mouse could be better
MacBook Pro  | 10   | 2023-01-05   | USA     | 5     | Love this laptop!
MacBook Pro  | 10   | 2023-01-05   | USA     | 4     | Great but small hard drive
MacBook Pro  | 10   | 2023-01-05   | USA     | 3     | Battery life could be better
MacBook Pro  | 10   | 2023-01-15   | Canada  | 5     | Love this laptop!
MacBook Pro  | 10   | 2023-01-15   | Canada  | 4     | Great but small hard drive
MacBook Pro  | 10   | 2023-01-15   | Canada  | 3     | Battery life could be better
MacBook Pro  | 10   | 2023-02-01   | UK      | 5     | Love this laptop!
MacBook Pro  | 10   | 2023-02-01   | UK      | 4     | Great but small hard drive
MacBook Pro  | 10   | 2023-02-01   | UK      | 3     | Battery life could be better
// FQL

[
  {
    "name": "MacBook Pro",
    "sold": 10,
    "recentOrders": [
      {"date": "2023-01-05", "country": "USA"},
      {"date": "2023-01-15", "country": "Canada"},
      {"date": "2023-02-01", "country": "UK"}
    ],
    "reviews": [
      {"stars": 5, "message": "Love this laptop!"},
      {"stars": 4, "message": "Great but small hard drive"},
      {"stars": 3, "message": "Battery life could be better"}
    ]
  },

  {
    "name": "iMac", 
    "sold": 5,
    "recentOrders": [
      {"date": "2023-01-20", "country": "France"},
      {"date": "2023-02-15", "country": "USA"},
      {"date": "2023-03-01", "country": "Japan"}
    ],
    "reviews": [
      {"stars": 5, "message": "Beautiful display!"},
      {"stars": 4, "message": "Fast computer"},
      {"stars": 3, "message": "Mouse could be better"}
    ]
  }
]

CONDITIONAL LOGIC (SQL vs FQL)

FQL allows variables and conditionals without depending on outside language logic.


Date lastView = ( visitor.getLastView() != null)? visitor.getLastView() : new Date();
boolean isNewSession = ( lastView.add(timeout, "seconds") < new Date() );

// whether it be JDBC calls, ORMS, or PSQL,  
// any solution requires more than SQL alone
if( isNewSession ) {
    stmt.executeQuery(
      "INSERT INTO Visitor ( "
      +"(firstView, lastView, url, visitorId, viewCount)"
      +" VALUES ("
          + now.toString()
          +", "+ now.toString()
          +", "+ url
          +", "+ 123
          +", 1 )"
    );
  } else { 
    stmt.executeQuery(
      "UPDATE Visitor"
      +" SET"
      +" lastView = "+ now.toString()
      +", viewCount = " + viewCount+1
      +"FROM Visitor"
      +"Where "
      +"  visitorId = "+ 123
    );
  }
// Is this a new or continuing visit?
let lastView = visitor?.lastView ?? Time.epoch()
let isNewSession = lastView.add(timeout, "seconds") < Time.now() 
  
let visit = if (isNewSession) {
  log("Starting a new visit")
  Visit.create({
    firstView: Time.now(),
    lastView: Time.now(),
    page: url, 
    visitorRef: visitor,
    viewCount: 1
  })
} else {
  log("Continuing visit: #{lastVisit.id}")
  lastVisit.update({
    lastView: Time.now(),
    viewCount: lastVisit.viewCount + 1 
  })
}

As a database developer, I find Fauna's use of named functions for accessing indexes brilliant. It adds flexibility and versatility to my workflow, allowing efficient interaction with indexes using custom functions.

Yacine Hmito, Head of Technology at Fabriq

With FQL, Fauna marries simplicity with power. Now, we can do aggregation and projection more effortlessly than in MongoDB. FQL outshines SQL with minimal effort and complexity.

Matt Haman, CTO, Rownd

Get started for free

Ready to ship apps faster? Start today.

Quick start

Get up and running quickly with an interactive introduction to Fauna.

Read More

Sample apps

Get how-to guidance for building applications with Fauna.

Build a sample app

New to Fauna Query Language?

This guide can help you get started with FQL in under 10 minutes.

Read More

Workshops

Build complete applications using technology like AWS Services, Cloudflare, and more.

Read More

Learning center

Get an account and create a distributed, performant, strongly consistent database in under a minute. Connect your application with TypeScript, Python, Go, or HTTP. Experience the power and flexibility of a database backend that requires no clustering, replication, or partitioning configuration. Check our docs to start quickly and integrate with popular tools and frameworks. Want more? Chat with us. We can’t wait to see what you build with Fauna!

See why Fauna's strong consistency and replication are important in reducing application bloat and protecting from regional failures.

White Paper

The architect's guide to building scalable global applications

Download the guide

See why Fauna's strong consistency and replication are important in reducing application bloat and protecting from regional failures.

Blog

Beyond SQL: A relational database for modern applications 

Read more

Workshop

Build a globally distributed app using Cloudflare and Fauna

FAQ

What is Fauna?

Fauna is a distributed relational database with a document data model delivered as a cloud API. Fauna offers advanced querying capabilities, robust consistency guarantees, and comprehensive support for data operations. Developers can leverage Fauna’s strongly typed database language, FQL v10, to express complex business logic in transactions. With multi-region, active-active compute and a distributed transaction engine, Fauna ensures fast, reliable, and secure performance. Fauna provides flexible data modeling, global data access, and integrates seamlessly with various development tools and platforms. Fauna empowers developers to build new powerful applications faster, scale existing applications with confidence, and eliminates the need for server management with its serverless native approach.

How much does it cost?

Our pricing is designed to give you all the capabilities to build and test your applications for free. When you are ready to move to production, simply pick a plan that best suits your needs. For more details on Fauna's billing and metering, see our documentation: https://docs.fauna.com/fauna/current/learn/understanding/billing

How does Fauna support multiple tenants for my service?

Fauna allows you to have a hierarchy of databases that can create silos for your customers. Fauna’s attribute-based access control and integrations with identity providers provide multiple levels of security. Further, if you need to geographically restrict data locality, Fauna is fully compliant with GDPR, and you can choose to have dedicated topologies across the globe.

How much bandwidth do I get?

Depending on which plan you select, you will get different levels of bandwidth. For more information on our metering, you can see our documentation.

Does Fauna have any tools to help me migrate off of my current database?

Fauna provides robust tools and support to assist you in migrating away from your current database. Our dedicated solutions team specializes in ensuring a smooth and hassle-free migration process, helping you seamlessly transition to Fauna's powerful database platform. Feel free to reach out to our support team to initiate the migration and receive expert guidance every step of the way. Your data's secure and efficient migration is our top priority.

How does Fauna support multiple tenants for my service?

Fauna allows you to have a hierarchy of databases that can create silos for your customers. Fauna’s attribute-based access control and integrations with identity providers provide multiple levels of security. Further, if you need to geographically restrict data locality, Fauna is fully compliant with GDPR, and you can choose to have dedicated topologies across the globe.

What is Fauna Query Language (FQL)?

FQL is a strongly-typed database language that combines the ability to express declarative queries and functional business logic in strongly consistent transactions. FQL is familiar to developers with prior knowledge of programming languages like TypeScript. The language is by nature composable and modular, allowing developers to query for documents at rest, encode sophisticated business logic and dynamically construct JSON-like result shapes that map to what the application requires. Designed for operational use cases, FQL combines Fauna’s powerful distributed architecture to make working with operational data productive, scalable, and secure for every software development team.

I’m a SQL user, why should I learn yet another query language?

Fauna is a document datastore and we at Fauna see the JSON document as a rich, expressive data model that is superior to the rows and columns of a traditional relational database. SQL, although it is an expressive language, principally deals with flat data in the form of relations (tables), and is not fundamentally best suited for operational use cases. Our goal at Fauna was to design a language that truly harnesses the power of a strongly consistent, transactional, document database.

Ready to get started?

Sign up or get in touch with one of our experts and discover why thousands of developers love Fauna.

Start for freeRequest a demo