How Landen Works: The Tech Stack
Hosting websites for thousands of customers as a one-man operation can be a challenge. The systems have to be scalable and reliable to provide high up-times with fast responses. At the same time it, can't be too expensive or time consuming.
There's only one way to achieve that: simplicity.
I built Landen with the technologies I knew when I started: React, Go, PostgreSQL, AWS. Here's how that comes together. Note that I've included a lot of links for easy reference, I'm not affiliated with any of the services mentioned.
The React app itself is built with create-react-app. Here are some interesting dependencies I'm using:
date-fnsfor date formatting (much smaller than moment.js)
frappe-chartsa beautiful and lightweight charting library
react-loadablefor code-splitting (keeping the app size low)
react-selectfor select menus (even though the file size is huge)
react-virtualizedfor performance in big lists
slatefor the blog editor
bugsnag-reactfor error reporting
fuse.jsfor filtering lists
When adding new dependencies I'm always very careful to keep the bundle size low. Even with minifying and compression, some dependencenies can easily 10x the size of your web-app, and thus it's load times.
In terms of UI, I didn't use any frameworks because I'm a big fan of experimenting with UIs and like to write them from scratch. That usually means things take a bit longer, but it's a rewarding experience. The only 3rd-party UI library I'm using is normalize.css.
With the React app itself I try to re-use components as much as possible, and keep complexitiy low. At the time of writing, the entire frontend contains about 25,490 lines of code (without the dependencies dependencies).
This part of the stack is there the data is stored and processed. It's a little more complicated than the front-end and consists of 4 main parts:
- API server: sends data to / and receives data from the React App.
- Site servers: host the actual sites created with Landen
- Certificate Server: for managing SSL certificates
- The database: where important data is stored
All of the back-end servers are written in Go and hosted on AWS EC2. The database is a managed PostgreSQL instance hosted with AWS RDS. Not having to manage the database server itself is a great relief for a solo developer team.
The API server is what some would call a monolith: it handles nearly everything when it comes to data processing, handling, authentication, and whatever else the React App needs. It currently provides 99 REST-ful endpoints, which is still a very manageable amount. The API server lives behind a Load-Balancer which makes it possible to scale up, if the need ever arises. However, to this day a single server has been able to effortlessly handle the entire workflow.
The site servers are responsible for figuring out which website to show when a visitors goes to any Landen site. They are also hosted behind load-balancers to increase redundancy and handle traffic spikes. Just like the API server, there hasn't been a need yet to scale up the site servers, despite the amount of traffic they are receiving. Since they are mainly serving static content, the computing power they require is very low.
The certificate server works in the background to request SSL certificates via Let's Encrypt. There are some ways to do this more easily without a separate server, but those come with limitations. Because Landen has multiple site servers which all need the latest certificates, it's best to handle all of that in one place instead.
Finally, the database is a simple AWS RDS instance so there's not much to manage from my side. There are no NoSQL databases in Landen's stack at this time, and maybe never will be. NoSQL sure has it's place in many applications, but it's often just used because it's hip and cool while the data it stores might never exceed the limitations of a basic SQL setup. Since I need to keep things simple, I'm trying to avoid them for now.
To help manage and extend the functionality of the stack I use:
- Hyperping for uptime monitoring and status pages
- Postmark for transactional email sending
- SendGrid for all other email
- Imgix for image hosting and processing
- CloudFront for other static assets
- Sentry for error reporting
- AWS S3 for larger data such as site files
- Pusher for real-time applications
That's it! A pretty simple setup for now, let's see how long it can keep up with growth. If you're curious about any aspect of the stack in particular, or need some advice for your startup, let me know on via Twitter.