Philosophy
The ambition of TrailBase is to help solve common problems with established, standard solutions, while being blazingly fast, avoiding lock-in, or getting in your way. You shouldn’t have to fight your framework due to evolving product needs. Instead, you should be able to use SQLite to its fullest, extend it, or move on entirely if necessary.
The key for TrailBase to achieve this goal is to focus on loose coupling and rigorous simplicity. Performance is merely a desirable side-effect of keeping it simple and carefully picking the right components for doing the heavy lifting.
Simplicity
To avoid demoting simplicity to just another popular marketing term, let’s start by clarify what we mean. Simplicity is a relative property in the context of a problem: a simple solution for a simple problem is straightforward to understand, validate, extend or even replace. A simple solution solution for a hard problem will naturally be more involved but retains above properties within a more complex context.
“Simple” is different from “easy”. An easy solution may be very complex in an effort to take on as much responsibility as possible for very specific scenarios. Easy solutions will sometimes yield pleasing but magic solutions that fall flat when straying off the path. Magic solutions will always lead to tight coupling and lock-in. In contrast, simple solutions are explicit, apply in a wide range of scenarios and lead to easy-to-understand, easy-to-change outcomes.
Why should I care? We believe that there are material benefits to simplicity. For example and tying back to TrailBase:
- A simple, single-file backend dependency lets you set up consistent production, pre-prod, testing and development environments, which will help to improve velocity, catch issues sooner, and reduce cognitive overhead.
- Lets you change production deployments or cloud providers more easily to address soaring bills, ToS changes, geopolitics and policy requirements such as data governance.
- Lets you more easily adopt TrailBase, also selectively, and more easily drop it if you choose to.
Coupling
The way we defined simplicity above, loose coupling is already an important property of a good-natured, simple solution. Yet, we believe it’s a critical property in its own right that should be called out explicitly helping to illustrate the guiding principles underpinning TrailBase. Looking at two examples:
Admin Dashboard: TrailBase offers an easy-to-use, integrated admin dashboard. It doesn’t make TrailBase architecturally simpler but hopefully easier to use. Importantly, it’s loosely coupled to the rest of the system. It’s neither critical for serving production traffic nor setting up TrailBase. Any dashboard task can be equally accomplished using the CLI, the configs, or SQL.
SQL over ORM: TrailBase embraces SQL instead of trying to hide it. Eventually all paths lead to SQL as the only truly cross-platform, cross-database, cross-language solution 😉. ORMs often yield simple looking examples but then fall flat soon after going beyond the tutorial, sometimes already when joining tables. Your data model should never be driven by the short-comings of an abstraction forced upon you. ORMs aren’t without merit. Often they will provide type-safe APIs for accessing the database. While more constraint, TrailBase’s end-to-end type-safety provides similar benefits. Leaning into HTTP, JSON and JSON schema to makes it easy for TrailBase to provide consistent cross-language client-side type-safety 1, giving you more freedom in choosing the right tool for a specific job.
Footnotes
-
Having only TypeScript and Dart bindings at the moment, this may sound more aspirational than practical. However, client bindings are only very thin layers around HTTP + JSON. It is straight forward to add new bindings or just use
curl
in a bunch of shell scripts. We’re planning to add more bindings in the future. ↩