What frontend engineers should know about backend
The vast majority of things a frontend engineers need to do can be done without knowing anything about the backend other than the API. If you work on different parts of the frontend for long enough though, you'll probably run into something that does require some backend knowledge. Here's the short list of topics that a frontend engineer should know about the backend.
The backend has finite resources and can only handle a certain rate of requests. In general, you should not care — the frontend should do what it needs to do to create a great user experience and the backend can optimize and scale. Still, network requests to the backend are not free, and they are not all equally expensive (in terms of resources used).
How do you measure how expensive a call is? A rule of thumb is that writes are more expensive than reads, so the more data is changed, the more expensive it is. An example of when this would be prohibitive: let's say you're implementing Google docs. You want the user to never lose their work if they exit, so you save often. Can you save on every single character insertion and deletion though? Your backend servers would probably not be able to handle it, or the cost of infrastructure to handle it would be unnecessarily high. Throttling to only save after the user stops typing can achieve 99% of the intended effect without the huge cost of the extra 1%.
Let's say you want to poll your backend for changes. You want the most up-to-date version of a doc, so how often should you make a request? Reads are much cheaper than writes, so you can do it more than writes, but there's still a limit.
The limit depends on many factors, like max number of active clients at any given time, backend infrastructure, and budget. If you think a change you're making might approach the limit, talk to the backend team. Otherwise, you might end up DDOSing your own company.
You should expect and prepare for every backend request to fail at some point for some users. It's an inevitability that the backend will go down at some point, or for specific endpoints to fail while the rest still work. You should distinguish which calls in your app are critical where a failure constitutes showing an app-wide error screen with a message to try again later, and which calls can be handled with graceful experience degradation (e.g., grey out the button for that feature with a hover error message saying it's currently unavailable).
The backend and frontend should use the appropriate HTTP status codes (to an extent). Hopefully your backend doesn't treat every error as a 400, but some will for simplicity. The frontend should know every status the backend plans to return. Don't parse error messages to detect a sign-in failed, a 401 is more consistent. Don't retry the exact same request if you're given a 400 because it probably won't work again, but a 500 might indicate the server is just rebooting and a retry would succeed.
Other properties of HTTP worth knowing:
- HTTP requests can be closed by the server if it takes too long to finish. If you think some task might hit that limit (~20 seconds is a good rule of thumb), you should switch from a single request-response to a request followed by polling for the result, or a different mechanism like web sockets.
- If you're sending large amounts of data back to the server (e.g. a video), you should use a multipart HTTP request, which splits the data up into chunks to be sent.
- Something that occasionally comes up unexpectedly is that there exists a URL limit size. Some frontends will pass data back to the server with query parameters, but if it's past 2048 characters, you'll have to switch to encoding it in the HTTP body.
Delegate business logic
If some business logic for a feature you're building can be done on both frontend and backend, where should you encode it? In general, you should do it on the backend. Reasons:
- The backend can be changed much faster — one deployment to all the servers and the stale business logic is gone, but frontend clients are in the hands of users, and a deployment doesn't mean you won't still have the broken business logic running in production.
- If the business logic requires computing power, it's hard to test the spectrum of machines your client might run on. If you're only testing with your company-provided top-of-the-line Macbook, you won't realize how much slower the computation might be a $100 Chromebook.
- It's more secure to lock business logic on the backend. Let's say you have a feature that only pro users can access. If you only encode the restriction on the frontend, someone could potentially reverse engineer your client via the API calls it makes, and access the features. This happens in the wild (e.g. music players that bypass limits).
Cross origin requests
As a security protocol, if a request to the backend comes from a different domain, it will be rejected due to being a "cross origin request". This is called the "Same Origin Policy". This trips people up in development, because ports count as part of the domain, and people are usually running an NPM/Yarn server for their frontend and the backend on another port, thus making every request a cross origin request.
- Map your server domains to some hostname in your dev environment's host config.
- Enable cross origin requests on your server conditional on an environment variable that's true in development and false in production.
- Whitelist your development domain as an exception.