Let's all agree on one thing: Writing backends is hard, and we suck at it.
Yeah, sure, we're all great at creating our Express server, with our MongoDB or MySQL attached to it, but what comes after?
Are you sure that your dedicated server is ready for when your app starts being successful? Yeah, you could optimize your server, harden your Linux, remove unnecessary packages, stop services, etc. Still at some point, you'll need to scale up your server, buy a more expensive one. But what if that is needed for only that moment when a high influx of users come into your site? Do you downscale to keep your budgets down? Do you keep paying for the server? Have you even thought about adding a load balancer?
The solution is obvious: Serverless and the cloud!!!!1!one!
Sadly, this is not the reality. Why not? Because it's just more stuff to learn, and it's not like learning a new library/tool, it's a ton of info. Have you considered your cloud already? AWS, Azure, Google Cloud Platform?
Let's suppose you chose AWS, here are some more questions: Will you use DynamoDB? Or Aurora? Do you know how to query those databases? Are there any ORMs available for your language+database combination? Are you deploying all of this infrastructure manually? Or are you using something like Terraform or Serverless? By the way, how comfortable are you with YAML? π
Not only that, now your code gets executed in separate functions. Don't try packaging your entire Express server into that. Well, at least if you value your wallet π
Did you think already about the architecture for your app? Will you communicate the different parts of your app through a queue? Will you do direct calls? Are you gonna store stuff in the database directly? Or is it gonna act more as a cache? π€
Also, remember that you have to create a proper SDK on the frontend to interact with your backend.
OH! I nearly forgot! Are you gonna add analytics to your app? Because it'd be good if you thought about that in this moment, where you can start gathering data right from day one.
And as a final note: Good luck maintaining it. π
You might be one of those people who see the text above and think "And what's the issue with all of this? It's part of the journey, I'm okay spending 95% of my time learning all this stuff and maintaining it, I'm a developer".
Sorry, but in that case, you're missing a lot of good stuff.
I think that we all agree that tinkering with pointers and registers is not something from nowadays' daily development scene. Sure, there is this small percentage of people that do this in order to optimize the speed of their system, but it's not the vast majority of us. Why? Because of speed of development.
The usage of those things have been abstracted for us, so we write less code that doesn't matter, and write more of the code that matters: The one that makes our app different
Same stuff with fonts, you don't design a font each time for your application, but rather, you just choose the one that fits best for the use-case.
What if I told you that there's a way to abstract all of this hard stuff regarding to backend development, and just focus on what matters in that code that makes your app different?
Enter Booster framework
Booster is this TypeScript framework distilled from years of experience working with companies like eBay, PayPal, Rent the Runway, or Zara. The folks at The Agile Monkeys got tired of reinventing the wheel constantly, and created the ultimate backend framework.
The premise is simple: Make developers' lives easier.
So, what makes Booster special?
It:
- Requires no prior knowledge of backend development.
- Frees you from thinking about servers.
- Eliminates the need to configure your database.
- Avoids having to configure endpoints.
- Deploys to your favorite cloud, without having to read their docs thoroughly.
- Removes any costs for your deployed app while youβre not using it.
- Has built-in analytics data gathering for your app.
- Is extensible with plugins in case you really want to tweak something (we call these rockets).
Also, you don't have to be thinking in architectures, Booster has thought that already, extracted from the enterprise projects above and many others.
Ok, how does one use it?
I'm not gonna get too deep into actual usage, because this is not a tutorial, but I'll show you enough to see what's going on when you work with Booster.
When you use Booster, you interact a lot with the boost
CLI tool that comes with it. Booster has a tiny bit of boilerplate code, but you don't want to write even that one.
How does one configure their app? That's the magic, you don't! The only thing you have to do is write your app around the following concepts:
Commands
A command is a class with some fields that represents an order to your system, along with a handle
method that will validate those fields, registering some events (we will talk about them in the next section). Examples of commands are generally the continuation of the sentence "A user can...", e.g.:
- A user can deposit money
- A user can send a message
- A user can create a chat room
How does a command look in practice? Just TypeScript code, and the best part, is that most of it is autogenerated! With a command like boost new:command DepositMoney --fields accountId:UUID amount:number
you'll get a file under src/commands
with the following contents:
@Command({
authorize: ...
})
export class DepositMoney {
constructor(
readonly accountId: UUID,
readonly amount: number
) {}
public async handle(register: Register): Promise<void> {
register.events(...)
}
}
You would now specify who can execute this command in the second line, write your validation code inside of the handle
method, and register the events. THAT'S IT! No HTTP methods, no routing endpoints, deep controllers, or whatsoever, just the important code.
Events
Same as commands, events' code is autogenerated with a command in your terminal, they are a regular TypeScript class as well.
Remember when I said that your app integrates already the data gathering for analytics? It's because of events! Instead of changing your database, performing queries, etc. You just represent that change as an event. Booster will store all these events infinitely, meaning that at any time, you can check what steps did a user do in order to trigger that bug, see if those users are dropping your registration process due to UX or a bug, think in how to optimize new features, and much more!
Examples of events are facts that you can state after a command, many of them are pretty obvious:
- Deposit performed
- Message sent
- Room created
(Note the ed
)
A newly created Booster event looks like this:
@Event
export class DepositPerformed {
public constructor(
readonly accountId: UUID,
readonly amount: number
) {}
public entityID(): UUID {
return this.accountId
}
}
Entities
Entities are the internal state of your application, but you don't modify it. Instead, Booster does something like an Array.reduce
to this infinite list of events that you have, to convert them into a tangible object. Entities have many uses, but the most important one is snapshotting, so your backend is FAST.
Examples of entities are concepts in your app, stuff like:
- Bank account
- Conversation
- ChatRoom
Here's an entity that calculates its balance
from the DepositPerformed
event, initializing balance
to 0
in the case that the account doesn't exist yet:
@Entity
export class BankAccount {
public constructor(
readonly id: UUID,
readonly balance: number
) {}
@Reduces(DepositPerformed)
public static reduceDepositPerformed(event: DepositPerformed, current?: BankAccount): BankAccount {
const currentBalance = current?.balance ?? 0 // ^-- Note how this is optional, because at the beginning of your app, the account doesnt exist
return new BankAccount(
currentBankAccount.id,
currentBalance + event.amount
)
}
}
Read Models
Read models are the way you expose your entities to the public. Read models act as a cache to make sure that your app gets the data ASAP. Also, they allow you to combine different entities, and transform the data in a way that it makes sense for your frontend. Again, a regular TypeScript class:
@ReadModel({
authorize: ...,
})
export class AccountReadModel {
public constructor(
public id: UUID,
readonly balanceMessage: string,
) {}
@Projects(BankAccount, 'id')
public static projectBankAccount(entity: BankAccount, current?: AccountReadModel): AccountReadModel {
let message = "Broke"
if (entity.balance > 1000) {
message = "Has sum money here, yo"
} else if (entity.balance > 10000) {
message = "Hey, this person is saving for sumthin'"
} else if (entity.balance > 100000) {
message = "Whoah, they gonna buy a house or what?"
} else if (entity.balance > 1000000) {
message = "They got a shit ton of money, yo!"
}
return new AccountReadModel(entity.id, message)
}
}
That's it!
Now, to deploy this, you just write boost deploy -e production
.
AND THAT'S IT. PERIOD.
No configuration, no control panels, no YAML, no anything! Just press one damn button, and you have your app deployed to the cloud
You get your cloud properly configured, with all security measures, architecture, interconnection of services, etc.
Booster spits out a URL which is a GraphQL endpoint for you, and that's it.
Right, but how do I connect this to my frontend?
Because it is GraphQL, you can perfectly use a library like Apollo in order to connect it.
Using React? Vue? Svelte? Elm? No problem, just use the Apollo adapter for one of those. No need to write SDKs/services for talking to the backend.
Commands can be executed through Mutations, Read Models can be queried or subscribed to. That's it, no need to encode URLs, remember parameter orders, create API documentation with Swagger, etc. Just use what you coded.
This is too good to be true, it must cost a lot, right?
Nope, the framework is absolutely free to use and open source. If you are worried about the costs of the cloud, all Booster projects
are eligible for the AWS free tier, and even without it, for 40.000 (that's forty thousand, btw) requests in one month, you'd pay less than one dollar.
(No, the team doesn't get any cut from cloud providers, we are just fed up with tools that create problems instead of solving them π)
Ok, what to do now?
If you reached so far, congratulations, and thank you! Nowadays frameworks appear every day, and people just roll their eyes. Booster is truly different and groundbreaking. For learning more, checkout the project's website, where you can find links to documentation, demos, and much more.
I also recommend you to join the project's Discord server and challenge it with your ideas, thoughts, and questions. A project is nothing if it stays in the same place, and by challenging it, you are already helping!
Booster is also part of Hacktoberfest, in case you want to contribute wink wink; nudge nudge. And even if not, a star in our GitHub repo would mean a lot.
Stay tuned for more!
May your day be awesome, and your backends easy π,
Nick