What Makes PostgreSQL, NodeJS & GraphQL the Best Base to Stack Upon?
Jeremy Bradbury
Seasoned SWE | NodeJS | JS/TS | GraphQL | IAM | React/Svelte/Vue | AWS | Git | CI/CD | Music
The *important* fine print
There's clearly a lot of debate around all this, everyone's experiences are different & you are quite likely to disagree. In any case, the title is not clickbait or spam, it's the actual subject of this article. I can only ask you to remain as objective as possible while reading this very opinionated piece. If I am going to change any of these things, it won't be from reading the comments section. It will be how this opinion was first created: through experience. I understand the same is likely true with any well formed opinion. My intent is not to change the minds of other developers. But perhaps change the way we (leaders, architects and developers) think about building stacks, by sharing where I think priorities should lie.
I've also left out a key piece I feel nobody needs to defend or explain: Nginx. I'll just mention one thing. Static files should always be served by Nginx in production.
What makes NodeJS the best of backend?
For me, it's hard to point at one thing. As a polyglot full stack dev who loves to learn, I left dying languages for what was clearly the future. The fact I jumped ship from PHP & Java backends (that were half JS anyway) along with my clients & never looked back, frames my bias well here. However, it's important to note, most of the competition’s supporters point to 1 thing about their chosen language/framework, like: "Look at this popular sterile/clinical benchmark, that only uses the most basic parts of each framework, it shows mine's better or close enough." I have never seen a performance benchmark that uses any of the Node C/C++ API for resource intensive operations, compared against something like Golang, doing the same resource intensive operations.?
Node is typically dismissed as a JS framework, often erroneously called a "frontend framework", when it's clearly so much more. That "close enough" claim about performance is the most accurate part of that argument, about any framework, making performance nearly the last concern. Some devs/orgs are clearly still defending beasts with inefficient file system interfaces (abstractions of OS operations, rather than a direct API) like Ruby on Rails & Python for reasons like talent pool and tooling. “Just add hardware” seems like an easy/obvious choice for most engineering directors who don’t like change or the job security that comes with adaptability.
Node started with async processing patterns, changing how multitasking was done on a server completely. This was not originally intended to replace threading, but in use it was fast and allows clean multiple instance per db concurrency. It was faster than most threaded systems, even on smaller/leaner server instances, while threading was delayed and types mostly ignored, as the intent was matching browser APIs. Later the rest of tech started catching up, adopting some async style processing (but not in the core, usually a framework). So Node eventually added web workers for threading anything you can run from the CLI, not just Node modules. It also uses Linux operating system tools under the hood (when NODE_ENV=production) to improve performance and it plays nice with tools like crontab and systemd. It even makes CLI (command line interface) tools easy without switching platforms.
Early on, a C/C++ API was added for backward compatibility and using common C tools. But most don't realize/remember/care that this API is layered nicely under the JS API. Core node modules like fs, http/s are compiled C/C++, not JS, which is what makes them so fast. But not everything you build in JS, with Node, is quite as fast. So you can have one C expert/team make something super performant, nearly assembly instructions for hardware, and your JS devs interact with it like any other NPM dependency. There are several NPM packages that are built this way. If you ever see "node-gyp" that's from the C compiler, building C source, using your device's compiler, inside the /node_modules folder.
Not just a JavaScript framework, NodeJS is a mature, highly supported server operating system (a polyfill for Linux Kernels), with the 2 most common, popular languages, C & JS, at its core, 4 total if you count C++ and TypeScript.
Why is PostgreSQL the best database engine?
The intended pronunciation is rarely used, like Gif & Linux. It's like taking the word "progressive" and replacing the suffix -ive, with the suffix -ual, as in... hmm... let's go with "contextual": "Postgres-cue-ual". I actually quite like it because it's witty enough to make me smile and makes a great point about their core values. "Postgres" is trusted by banks, hospitals and ecommerce platforms. It's open source & "free as in beer" (Google it if you must). Unlike how commercial open source often goes (looking at you Google, for close sourcing Android after Amazon Kindle/Fire), when paid competition like Microsoft, IBM & Oracle started making exact copies of their features, the Postgres community said "bring it, can’t stop/won't stop" with their actions. So these expensive to license database engines aren't nearly as feature complete as Postgres and simply “borrow” some of their best features after we test/use/ask for them, instead of being original in any way that matters. If you need stability & hate new features like Microsoft’s SQL team, you can still use 9, 10 or 12 instead of the new version 14.
When you get beyond those superficial notes, you realize amazing things like "hey I can do all the same statistics, standard deviation & regression work from R and numPy, but right inside the source of truth, in an (arguably) easier to read format".? I can hear the rumblings already: "what about NoSQL". Well, I'm glad you brought that up. “Postgres did that first too & still does it better” - me. You can fit a whole MongoDB into a single Postgres table, a whole table into a JSON/B field. Let me break this down a bit. But first I’ll admit my obvious bias, which was revealed in the quoted post above.
Imagine you have a User object with a variable schema in Cassandra or Mongo. A really wide column, some small, some large, some have a profile, others don't. In a relational database we'd likely have at least 2 tables (possibly starting as 1), one for profile and one for user, so that we don't have a bunch of empty fields on rows with no profile. This means we can optimize performance on this object, by making it a little harder to work with. That last sentence is the key difference between relational and NoSQL patterns. But Postgres gives us a third, hybrid option, which makes prototyping in NoSQL with Postgres a great choice as we can roll into more performant patterns.
The hybrid approach to NoSQL is easy, you have a single JSONB field with smart indexing, and an auto-generated UUID field. Now you can relate your user to your profile by adding a third UUID field to your user. A single null UUID field wastes far less partitioned space than a whole row or object. Did this increase performance? Probably not, but perhaps decreased storage. What it really does, is help reorganize the schema into relational, and start pulling out fields you could sum/min/max with efficient, grouped queries. Those kinds of queries Cassandra, Dynamo & Mongo fail at, because they are focused on treating every object as an individual. When we try to operate on users or other objects as a group, that's where NoSQL engines truly let us down.?
So why would you prototype in a NoSQL engine, only to convert to at least a partly relational pattern as the application grows? A single PostgreSQL JSON/B field in a single table works just as well for schemaless prototyping.
Why is GraphQL better than the REST?
So many humans who don't build/use RESTful endpoints, will likely never fully understand any of what I'm about to explain, but I'll try. And if you are a backend, frontend or full stack dev you know exactly where this topic paragraph is ending...
It's all about accurate documentation.
There are so many things to like about GraphQL, but it's really that GraphiQL (pronounced as graphical) solves documentation, using clever automation, empowering developers to focus time on more crucial problems. The biggest challenge a frontend or application developer will face (when using REST) is getting the API calls right. Why is that? Because backend devs are human. We update the code but not the docs or the docs and not the code. A painful dev-to-dev communication cycle ensues over Git issues and Jira tickets. There is no good way to ensure the documentation matches the code, without developers testing it. Or is there? If you generate documentation from the code, you've solved several problems. This not only keeps the code and documentation in sync, it essentially replaces the need for endpoint integration testing, making it a formality, only if you like? protecting your CI deployments.
领英推荐
Shouldn't front end teams focus on optimizing UX, instead of API calls??
GraphQL, created by/for Facebook (now called Meta), is a powerful query language like SQL, that can be exposed to clients in a controlled context. So essentially it's like "SQL from the client, with custom rules backend sets on the server". Sounds similar to what REST attempts to accomplish without trying to put a function name and some, but not all, variables into a URL and http verb, right? The language allows us to strongly type our requests and results beyond Number, Boolean and String, with dates as plain strings.
Before React was open source, before GraphQL was open source, there was the Facebook Graph API. Around a decade ago, during my time at Janrain, now Akamai's Identity suite, I worked deeply with the early Facebook Graph API. Just as I knew NodeJS's ExpressJS would replace Laravel's Dingo & Java's SpringBoot, I knew React would replace PHP templates, and GraphQL would replace REST & was what we needed to complete React. I knew that Redux was a maintenance nightmare not worth my time & Relay was broken unless we can make changes in the client cache. That last one is pretty much how Apollo Client's in memory cache works now.
Even without a client tool (using axios/fetch/libcurl instead), GraphQL is still a better option than REST, partly by design, but mostly because of the documentation.
Today, GraphQL has essentially replaced REST (circa 2000), an API pattern recently old enough to drink alcohol in the US. Some companies feel stuck with REST for now, but they don't have to. The same way GraphQL resolvers can send off an API call to a third party (or even like the Postgres hybrid approach above), they can be aimed at internal RESTful APIs, then slowly convert each endpoint into the Graph itself if needed. This instant middleware fix, makes it easy to monolith your microservices together, then address performance issues individually. Apollo servers adding federation has made the final concern/challenge of GraphQL adoption super easy, and entirely without Meta’s GraphQL codebase (another sticking point for some).?
On top of all that, GraphQL services and clients are available in any language, so you can install it on the same server with SpringBoot ?or Laravel, without needing another platform or even package manager.?
How do we wrap this up?
Most of the popular media and broadcasting companies, like Medium, LinkedIn, NYT, Netflix, Hulu, HBO, NBC and Disney, are using this tech, even if they aren't exclusive to it. Fortune 100/500 (esp media) seem to lead by example in 2021 and more rigid verticals like banks and healthcare usually aren’t far behind. Adoption & usage rates for all of these are very high now, because it really is the best stack. It may not always be the best at one thing, but IME you want your stack to be good at all the things, while remaining simple to get right.
If you have one stack that hits all the performance minimums, lacks need for complex optimization techniques and makes dev's work lives better through documentation & automation, it's really hard to compete with that.
Are you seeing a pattern? Not just a pattern of highly acceptable performance, but adaptability, mass adoption, high usability and large unwavering open source communities ready to pick up the slack when someone falls down or goes away. These are/were leading edge technologies that have recently become mainstream and for some excellent reasons. Those reasons include a great experience for DevOps, Backend, Frontend & Application devs alike, things that they can agree on that make their work lives better & more enjoyable. Even if this was the only benefit, doesn’t happy talent make this core stack a worthwhile choice, all on it’s own??
The “Best Stack” architectural philosophy series started with? “What Makes NodeJS, PostgreSQL & GraphQL the Base to Stack on?”. We discussed the core platforms that would make the platform on which we built a stack here.
Up next "What Makes the Best Web Stack?” We will discuss amazing tools which tie the core platforms together, into a really fun, performant, automated and easy to maintain stack to accelerate prototyping and development, while still easily scaling to enterprise usage requirements.
My Design Philosophy - or "About the Author"
I believe in putting humans first, it's the machines that were built to serve us... right? (Don't tell Skynet I said that). We should fit technology to human, like ergonomics, in order to support them in building the best quality products. Developers, including the DevSecOps and SDET teams are not just scientists, they’re artists, who deserve the best tools and creative freedom. Beyond that, it's all process optimizations.?
You’ll never convince me that a great integration test, schema or even code snippet isn’t art. That said, my mind is always open to change, it will change after this article, because I am focused on always finding “The Best” of everything.
There are no `static final` definitions in life. Change & uncertainty are the only true constants.
Disclosure: I am not affiliated in any way with any products featured here, other than my limited open source contributions on GitHub.
There are obviously many conflicting opinions here. But this is LinkedIn, not Twitter or Reddit. We avoid attacks on others, simply because they disagree. Comments here are focused on how great opinions are and how they differ or align from others'.
`Different != Wrong`