Table of contents
- Determine if the static and dynamic content can be served closer to the user.
- Determine if you want to serve content via HTTP2 for increased performance.
- Determine whether to serve content from multiple domains from a dedicated IP address.
- Determine whether to restrict content access to authenticated users only.
- Determine the content update versioning.
- Determine the caching policy to reduce latency and network traffic.
- Check if CORS is set up correctly.
- Check if data compression is enabled to reduce bandwidth and latency.
- Check if a web firewall is enabled to prevent common attacks.
- Check if DDoS protection is enabled.
- Check if you logging and monitoring is enabled.
Content Delivery Network (CDN)
Determine if the static and dynamic content can be served closer to the user.
- Serve static content (e.g. files like pdf, videos, images)
- Serve dynamic content (e.g. weather data via an API)
- Stream real-time audio/video
Determine if you want to serve content via HTTP2 for increased performance.
The HTTP/1
specification recommends opening up to two connections from a client (browser) to a web server. Modern browsers have removed this restriction and can handle more than two parallel downloads. This decreases page load time when downloading multiple assets (CSS, JavaScript files, images) for a single page view.
Domain sharding is an older workaround for HTTP/1
limitation by sharding the domain with multiple CNAME
aliases for the same web server.
HTTP/2
solves this with multiplex responses, by interleaving multiple responses in parallel without blocking. This allows the web server to serve multiple files at the same time in a single connection.
- Request multiplexing needed
- Server push for assets needed
- Header compression needed
- Keep it simple with
HTTP/1
Determine whether to serve content from multiple domains from a dedicated IP address.
Sometimes you want to host multiple secure domains e.g. https://mycompany.com
and https://api.mycompany.com
, each with its own SSL certificate, on a single web server which has one IP address.
The difficulty is that the SSL handshake between the server and clients happens before the clients can indicate the domain they want to reach using the Host
header.
Server Name Indication (SNI) is an extension of the TLS protocol which solves this issue by including the domain name in the TLS handshake, so that clients are able to see the correct SSL certificate for the website they want to access.
- Serve multiple domains with SNI
- Serve multiple domains via dedicated IP addresses
Determine whether to restrict content access to authenticated users only.
For example, only paid subscribers can download files.
- Restrict access with signed URLs
- Restrict access with signed cookies
- The content is available to unauthenticated users
Determine the content update versioning.
The recommendation is to use different file or directory names, for example image_1.png
, image_2.png
because you don’t have to wait for an object to expire before your CDN servers the new version (also, invalidations cost money).
Setting cache eviction policies (see below) is also recommended alongside versioning.
- Update content using the same file names
- Update content using a version identifier in file names
Determine the caching policy to reduce latency and network traffic.
- Set
Cache-Control
headers for caching policies - Set
ETag
orLast-Modified
cache validator headers - Use
Vary: User-Agent
to make platform-specific file versions discoverable by search engines - Set the default, minimum and maximum TTL
Check if CORS is set up correctly.
Cross Origin Resource Sharing (CORS) is a mechanism built in browsers to allow requests from the same domain but block rogue requests to a different:
- domain:
example.com
→api.com
- subdomain:
example.com
→api.example.com
- port:
example.com
→example.com:4000
- protocol
https://example.com
→http://example.com
The idea is to prevent cross-scripting attacks. For example, we don’t want Google Ads to make an AJAX call to your logged in bank account.
CORS works in the following way:
-
If the server doesn’t respond with specific headers to
GET
andPOST
requests, the request will still be sent, the response still received but the browser won’t allow the JS to read the response. -
If the browser makes a request with cookies or a custom header and a
Content-Type
other thanapplication/x-ww-form-urlencoded
,multipart/form-data
ortext-plain
then a mechanism called preflight is used and anOPTIONS
request is sent to the server instead. -
If the server doesn’t respond properly, only the preflight request will happen and the browser will display an error:
Access to fetch https://api.example.com from origin https://example com has been blocked by CORS policy...
CORS can be controlled with the following headers:
-
Allow-Control-Allow-Origin
- returned by the server
- indicates what client domains are allowed to access resources:
*
- any domain (anti-pattern)https://example.com
- if you require authentication headers (e.g. cookies) you cannot use
*
-
Allow-Control-Allow-Credentials
- required only if the server supports authentication via cookies
- the only valid case is
true
-
Allow-Control-Allow-Headers
- comma-separated list of request header values the server is willing to support
- if you use custom headers like
x-authentication-token
, you need to return it in this ACA header response to theOPTIONS
call, otherwise the request will be blocked
-
Access-Control-Expose-Headers
- the server makes available a comma-separated list of headers to the client, others are restricted
-
Access-Control-Allow-Methods
- comma-separated list of verbs
GET
,POST
- comma-separated list of verbs
-
Origin
- part of the request the client is making
- contains the domain from which the application is started
- browsers don’t allow you to overwrite this value
Bonus: Set the Content-Security-Policy
directives to allow loading javascript libraries only from your domains, to mitigate the risk of malicious third-party scripts.
- Set up
CORS
headers - Set up
CSP
headers
Check if data compression is enabled to reduce bandwidth and latency.
This makes website rendering faster, because files are downloaded faster. The amount of compressed data is lower than uncompressed, so it also reduces costs.
Clients must use Accept-Encoding
to indicate support for compressed files gzip
or br
and the server must respond with Content-Length
to determine the size of the file.
Comparing Brotli with Gzip, it has support across major browsers, it’s faster and produces smaller files:
- HTML files are 21% smaller
- CSS files are 17% smaller
- JS files are 14% smaller
Gzip
compression is enabledBrotli
compression is enabled
Check if a web firewall is enabled to prevent common attacks.
A CDN is like the front door of your house. You want to lock it, control who has access and ensure nobody can storm in.
A web firewall enables the CDN to allow, block or count requests matching certain rules.
These rules prevent common exploits like cross-site scripting (XSS) and SQL injection (SQLi) attacks and/or filters unwanted traffic, for regulatory requirements.
- Check IP addresses that requests originate from
- Check they country that requests originate from
- Check certain values in request headers
- Check regex strings that appear in requests
- Check the length of requests
- Check the presence of SQL code in requests to prevent SQLi
- Check the presence of a script in requests to prevent XSS
Check if DDoS protection is enabled.
A DoS, or a particular form if it, Distributed Denial of Service (DDoS) means that a single malicious source or a multitude of systems target a vulnerable network and flood it with packets.
Not only that legitimate customers cannot be served but apparently, the average cost of a DDoS is around $40,000 per hour 🤯.
A DDoS shield is a software that inspects incoming traffic and applies a combination of traffic signatures, anomaly algorithms, and other analysis techniques to detect and stop malicious traffic in real-time.
- Enable standard DDoS protection
- Enable advanced DDoS protection (i.e. real-time notifications of suspected attacks)
Check if you logging and monitoring is enabled.
- Enable logging
- Create alarms based on log metrics, for example for
HTTP 500
status codes