Gotta love some clickbaity titles! There is a reason why I chose this title however, and I invite you to start thinking about the code you write differently by the time you get to the end of the article. With all the caveats that if your view of software engineering architecture happens to match mine, yay, no more work needed!
Let us begin then! This is mostly going to be useful for folks who are probably mid-level, or just beginning their senior roles. Hopefully senior and above level people already know this, or at least have an intuition about it.
Regardless of language
When you have an idea for a product, or you work on a team that writes products, at some point you’re going to have a conversation about architecture. So what the heck is that?
It’s a shorthand for building (writing) an application / service / what have you in such a way that someone new, who is familiar with the language your thing is written in, can fairly quickly say “oh yeah, that part is for storage, that’s for caching, this part is validation, this bit takes in data from there”, et cetera.
All of these parts serve their own purposes, but what part is your actual service? Your actual product, your actual thing that you charge money for?
The way I like to think about it is that whatever ends up in production, on Netlify, Heroku, or wherever, is a collection of modules separated into two groups:
- your core app
- the parts supporting your core app
Your app’s core is the part that you can’t really change without your app ceasing to be your app any more. That’s the stuff that makes you unique in most cases, that’s the valuable bit that your customers are throwing money at you for.
The parts supporting your core app can be changed, swapped in and out, evolved, iterated on in response to your needs. Tools that provide something somehow, but the how is irrelevant to the core part of your app.
Let’s say you’re a service that sells image enhancement. Customers send the service an image, service does magic, and service sends them back the enhanced / doctored image. Maybe it’s adding a watermark. Maybe it’s fixing white balance. What it is does not matter.
Here are the parts of your service that you all need to deal with:
- a way to receive images
- a thing to return images with
- somewhere to store images
- something to authenticate users
- some sort of a billing thing with payments
- the part that does the image manipulation
Pop quiz: of the above, which part is your app? The core app? Which part(s) are only supporting it? Take a moment with this.
Core and not-core
In the above hypothetical service, the core of it is the part that does the image manipulation. Every other part is merely a tool to help with it.
There’s the storage. Sure you need storage, but what that storage is doesn’t matter. When you start out and the service is low traffic, the local disk on the server is probably good enough. When you get a lot more traffic, that won’t do, so something like S3 or some other storage will be needed. Your core does not need to care, it just needs a way to store and fetch things back. This is a supporting piece.
The part about receiving and sending out images? I think it’s also a supporting one. Do the users use file upload on a web form? Do they copy files onto an ftp server? Do they send a POST request? Do they send a GRPC request? Do they email you the file? Is it just a link? It doesn’t matter to the core, which only cares about an input image. How that input image made it there is irrelevant. You can swap them out. You can have multiple at the same time. As long as the side that’s facing your core looks the same, everything is fine.
Similarly sending back the result can be either an HTTP response with the image as the body, or an email with a link to a downloadable version of the altered image at some point. It doesn’t matter, because it can be achieved in various very well defined and solved ways. “Here’s an image, get it to the user.” Practically every service on the internet has a module that does something similar.
Authentication and billing are also kind of an accessory. That’s for your record keeping purposes, the core of your app doesn’t actually care about it. It’s probably an external shell around your core app anyways, and you could / should be able to remove it without having to touch any other code. It is entirely an accessory / tooling. See, the core app doesn’t, shouldn’t care about whose image it is. It gets an image, and an identifier to pass to other systems, and that’s it.
It’s the storage system’s responsibility to figure out where to store the images based on the identifier. If the user exceeded their plan tier? The core app doesn’t even receive the image, there’s no work to do. It’s already taken care of.
all the way down
I’m going to throw a pebble into the lake of the above.
Sometimes the REST API is the core product. Sometimes it’s not even a separate product, sometimes it’s a different team in the same company.
Stripe, for example, has a bunch of different teams. For one team, say payments (I don’t actually know as I don’t work, nor have I ever worked for Stripe), the REST API is just an accessory. For the API team, the API is the core product, and to them the core product is an interface they need to put their product over.
What your core product is really depends on a number of factors. Hopefully I managed to give you a framework along which you can have a think of your current core product and accessory tools.
Until next time, frens.