Three months ago, my team kicked off a greenfield project. We had a short timeline, big dreams, and one very exciting parameter (or lack thereof): no institutional commitment to any particular tech stack. We had a lot to achieve, but the world was our oyster concerning how we achieved it. In light of this freedom to choose our tools, our team took the opportunity to test out FaunaDB. I’m delighted to say that I’d pick this nifty little database over and over again.
In addition to a batteries-included frontend framework and a deployment + hosting solution that would get us off the ground quickly, we needed to choose a database to back the app.
Our parameters for the DB were that it allow us to:
- Favor development speed over long-term cost efficiency. The project is an application supporting a local event that runs for only a few weeks. Developer hours were more expensive than short-term premium hosting costs. We took any chance we had to solve problems with one to two months’ worth of SAAS fees instead of valuable sprint time.
- Handle rapid horizontal growth gracefully. When the event opens, we expect a sudden influx of users, all producing and querying for data associated with themselves. However, we don’t need to support many clients mutating the same data at once. A distributed database would allow us to take full advantage of the shape of our problem and reliably provide snappy response times to N clients.
- Prototype rapidly and change our minds often. The project was greenfield and very much an early beta. We needed to be able to flex to changing requirements as the software took shape and as our customer gathered new information.
Smarter people than me have written at length about the cool underpinnings of Fauna and its architecture and performance. Here, I’ll focus on the developer-facing features that made it a great fit for our scrappy, fast-turnover, greenfield consulting project.
Our Favorite Features:
A Hosted API…
Access to your Fauna database is all done via REST or GraphQL requests to Fauna’s public API. Although it’s more commonly done via one of their engines, querying for “give me all the accounts” can be as straightforward as:
curl --request POST 'https://db.fauna.com/' \
--header 'authorization: Bearer <your API key>' \
--data-raw '{"paginate":{"documents":{"collection":"accounts"}}}'
You don’t think about how it’s hosted, whether it has enough resources, or its uptime. For our customer, who didn’t have a dedicated DevOps team, this feature alone made a huge difference in the ability to support the project.
…That’s Pretty Dang Powerful
Queries to your Fauna database are made via their LISP-like DSL, Fauna Query Language (FQL). FQL includes the usual data-processing trimmings functional developers will expect of a query language. It also includes strong lambda support and some handy utilities for leveraging tools like Fauna’s built-in auth (more on this shortly). Indexes allow fast access and search on oft-used documents. If you’re handy with them, they can provide pretty sophisticated views of your data.
There’s also support for User-Defined Functions. These are custom FQL snippets that can be called like FQL functions and edited like any document in your database. This means that true serverless operation is very achievable. We had (almost exclusively) React components hooking right into the Fauna API, calling UDFs that handled our business logic, and querying for resultant data without a whiff of any custom server code.
I’d be remiss if I didn’t also note that FaunaDB comes with a GraphQL API out of the box as well. It looks very handy, but GQL didn’t make sense to pull in for our particular domain, so I can’t comment on the API’s efficacy.
Built-in Authentication + Attribute-based Access Control
There’s lots more to love, but for our team, Fauna’s most powerful feature was by far its built-in user authentication and authorization. Any document can be given credentials via a super straightforward Update($someAccount, { credentials: { password: "$ecret$" } })
call, and Fauna takes care of storing those credentials securely. Then, when a client wants to authenticate, Fauna provides an API to Login with and mints tokens. It manages sessions for you, no thinking required.
These things saved us an immense amount of time (see my previous point about favoring speedy out-of-the-box solutions). But, where this feature really shines is in tandem with the powerful public API.
When a client authenticates with Fauna, they receive a token that provides them attribute-based access control to the database that’s behind that public API. What this means is that any client can directly query the database. The ABAC made it feel almost like each client had their own private database to work in. Serverside queries are error-prone and enforce client permissions before querying a subset of a table. In Fauna, clients can ask, “give me all documents in Collection X” and receive back only documents and privileges they have access to.
NOTE: “Give me all documents in Collection X” is an interesting exercise of Fauna’s ABAC capabilities, but it’s not a good idea for production queries. You’re better off being more specific using something like “Give me all documents that are assigned to this user.” Otherwise, you force Fauna to check, and therefore query, the permissions for every last document in the Collection (ask me how I know)!
FaunaDB Might Not Be for You if:
You’re not into polyglot stacks.
FaunaDB’s cool DSL is powerful, but there’s a learning curve to it. There are some oddities about how it represents Fauna-internal types like Page
s vs. Set
s vs. Array
s that didn’t come naturally to our team. Additionally, there’s a verbosity to common operations that can get tedious. There are drivers for most major languages used on the web today that allow you to write FQL-like queries in your native language. But, at the end of the day, you’re still composing FQL. You’re probably better off just building that logic into plain FQL via user-defined functions.
You’re a TypeScript junkie.
I know, I know, but hear me out. Because Fauna is a NoSQL database that doesn’t enforce constraints on the shape of your documents, its JavaScript driver can only provide so much typing of the data you get back from it. You could work around this with diligent manual typing of query parameters and results. And a little birdie told us that stronger schema validation may be coming down the pipe soon.
Your team is very large or mostly junior.
FaunaDB is a pretty young tool in a world of Postgres and MySQL. That means it doesn’t have the decades of refinement and community contributions to developer ergonomics that the bigger dogs in the arena might. Its CLI tools can be rickety, and error messages can be cryptic. This means that to be productive, it’s important for your development team to be in close communication. There aren’t a lot of guardrails if someone gets off-track, and you’re going to be developing your own best practices as you go.
Fauna combats these challenges with the Fauna Labs team, a subdivision of the organization that produces example projects and developer tools. But, because those tools aren’t Officially Supported by the company, you can expect to trip over issues here and there. In particular, we’re looking forward to planned updates to their Serverless plugin and more ABAC features in the VSCode extension.
My Biggest Gripe
Testing. Testing in Fauna is tricky, but not impossible. In particular, you need to thoroughly test that business logic I recommended pushing into Fauna’s UDFs. However, there’s not much in the way of easy mocking tools or in-memory Fauna simulators that can run gracefully as part of your unit test suite. Fortunately, with the help of Fauna’s public Docker image, it’s manageable. Look out for a later post about how our team tackled this issue.
One Final Note About FaunaDB
The Fauna engineering team is hyper-responsive and very friendly. We received loads of advice, direction, and hands-on support via their public community Slack instance. The humanness and accessibility of the Fauna team more than made up for any the tricky moments we encountered. There’s no way to know if they’ll be able to maintain this close relationship with their customers as they grow. So, get your foot in now and soak up all that community goodness.
Thanks For Information