Web Hosting cheat sheet

A scannable Web Hosting reference: 24 short snippets across 12 topics, each linking back to the lesson it came from.

At a glance

TopicWhat it covers
Build and deploy workflowsA deployment should be the same actions repeated every time, on a machine that starts clean. Two rules make that worklesson
Custom domains and TLSHosting providers give you either an IP address or a hostname to point at. Use an A/AAAA record for an IP, and a CNAMElesson
Hosting models compared: VPS, PaaS, containers and serverlessThe question is not which model is best but how much operational work you are willing to own. A VPS is the cheapest waylesson
Choosing a host: cost, lock-in and supportAn SLA credit is a refund, not a remedy. A provider that credits you a day of hosting after a full-day outage has paidlesson
Environment variables, secrets and configurationRead configuration once at start-up and fail loudly if a required value is missing. An application that starts with alesson
Containers on a budget: Docker and managed container hostsCompose is for parity, not for production. Its job is to make the local environment match the deployed one closelylesson
Serverless and edge functionsA pool per instance with max: 1, plus an external connection pooler, is the pattern that survives a traffic spikelesson
Databases, object storage and backupsManaged database options, connection pooling from serverless, object storage and signed URLs, backup schedules, andlesson
Email, cron jobs and background workersDo not send application email from your own web server. Deliverability depends on reputation and on a providerlesson
Monitoring, uptime and log managementMetrics answer "how much" cheaply and over time; logs answer "what exactly happened" expensively; traces answer "wherelesson
Scaling: load balancing, autoscaling and stateless designThe order that works: make the application stateless, add a cache, move slow work to a queue, and only then addlesson
Security hardening, cost control and migrationsThe security control that fails most often is not a missing WAF rule, it is an unpatched dependency or a formerlesson

Quick snippets

Build and deploy workflows

Build once, ship the artefact

# local: reproduce exactly what CI will do
rm -rf node_modules dist
npm ci                 # installs from package-lock.json, fails on drift
npm run build          # writes dist/
node --check src/build.js 2>/dev/null || true

# inspect the output before shipping it
find dist -name "*.html" | wc -l
du -sh dist

Atomic release and rollback

# versioned releases behind a symlink
RELEASE=/srv/app/releases/$(date +%Y%m%d%H%M%S)
mkdir -p "$RELEASE" && cp -r dist/. "$RELEASE"/
ln -sfn "$RELEASE" /srv/app/current     # atomic switch

# rollback
ln -sfn /srv/app/releases/20260917120000 /srv/app/current
ln -sfn "$RELEASE" /srv/app/current

Preview environments and secrets

main        -> https://example.com
pr-142      -> https://pr-142.preview.example.com
local       -> http://localhost:3000

# build-time variables are PUBLIC once baked into the output:
PUBLIC_SITE_URL=https://example.com   ok
API_SECRET_KEY=...                    never - it ends up in the HTML

Full lesson: Build and deploy workflows →

Custom domains and TLS

Pointing the domain

; recommended shape: www is the CNAME, apex redirects to it
example.com.   300  IN  A      203.0.113.10      ; or ALIAS to host.example.net
www.example.com. 300 IN  CNAME  host.example.net.

; alternative: both served, one canonical
example.com.   300  IN  A      203.0.113.10
www.example.com. 300 IN  A     203.0.113.10

Certificates that renew themselves

# is the chain complete, and when does it expire?
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates

# does the www variant work too?
echo | openssl s_client -connect www.example.com:443 -servername www.example.com 2>/dev/null \
  | openssl x509 -noout -subject

Full lesson: Custom domains and TLS →

Hosting models compared: VPS, PaaS, containers and serverless

Mixing models deliberately

A common, defensible hybrid

  static assets        object storage plus a CDN      cheap, fast, no scaling story
  HTTP API             container host, 2+ replicas     steady traffic, predictable
  image processing     queue plus worker functions     spiky, latency-tolerant
  scheduled reports    a cron job on a small worker    long running, infrequent
  database             managed service with backups    the part you least want to run

Rule: put each workload where its cost curve is flattest.

Full lesson: Hosting models compared: VPS, PaaS, containers and serverless →

Choosing a host: cost, lock-in and support

The price is not the price

A quick cost model that survives contact with reality

  monthly = plan
          + egress_gb * rate
          + extra_requests / million * rate
          + database plan
          + storage_gb * rate
          + support tier

Do this for the current month and for 10x traffic.
If the second number is not survivable, the architecture is wrong,
not the provider - cache at the edge before you buy a bigger plan.

Lock-in, regions and SLAs

# check the provider's own infrastructure before you trust it
dig +short NS yourdomain.com
curl -sI https://provider.example/ | grep -iE "server|cf-ray|x-served-by"
whois yourdomain.com | grep -iE "registrar|expiry"

Full lesson: Choosing a host: cost, lock-in and support →

Environment variables, secrets and configuration

Configuration versus secrets

# .env.example - committed, contains names and placeholders only
DATABASE_URL=postgres://user:password@localhost:5432/app
REDIS_URL=redis://localhost:6379
SESSION_SECRET=change-me
LOG_LEVEL=debug

# .gitignore
.env
.env.*
!.env.example
*.pem
*.key

Injecting at runtime

Preference order

  1. platform secret store, injected as environment variables    typical PaaS
  2. mounted file from a secret volume, read once at start-up    containers
  3. a secrets manager called at start-up with the platform identity
  4. environment variables set by the orchestrator from a secret   Kubernetes
  ... 
  last resort: a file on the host with 0600 permissions, owned by the service user

  never: a secret in the image, in the repository, or in a build argument

Full lesson: Environment variables, secrets and configuration →

Containers on a budget: Docker and managed container hosts

Managed container hosts and tag discipline

# immutable tags: the commit sha, not "latest"
docker build -t registry.example/app:$(git rev-parse --short HEAD) .
docker push registry.example/app:$(git rev-parse --short HEAD)

# deploy the exact tag that was tested
kubectl set image deployment/app app=registry.example/app:a1b2c3d --record

# and keep a staging tag pointing at the same digest
docker tag registry.example/app:a1b2c3d registry.example/app:staging

Full lesson: Containers on a budget: Docker and managed container hosts →

Serverless and edge functions

Costs and background work

Making background work safe

  queue           one message per unit of work
  idempotency key so a retry does not double-charge a customer
  dead-letter     after N attempts, park the message and alert
  visibility      long enough that a slow job is not delivered twice
  schedule        from the platform, not from a self-scheduling function

Every serverless retry is a duplicate unless the handler is idempotent.

Full lesson: Serverless and edge functions →

Databases, object storage and backups

Choosing and connecting

Connection budget

  app instances        x  pool size per instance  =  connections
  serverless           x  1 per instance           =  unbounded without a pooler

Rules that keep a database alive
  set a small pool per process and a real statement timeout
  use an external pooler in front of a serverless platform
  never open a connection per request
  alert at 70 percent of the connection limit, not at 100

Choosing and connecting

-- a statement timeout protects the database from one bad query
alter role app set statement_timeout = '15s';
alter role app set idle_in_transaction_session_timeout = '30s';

-- and find the queries that are actually costing you
select calls, mean_exec_time, total_exec_time, left(query, 80) as query
from pg_stat_statements
order by total_exec_time desc
limit 10;

Backups that actually restore

# a monthly restore drill, scripted so it actually happens
pg_restore --clean --if-exists --no-owner \
  --dbname=postgres://app@restore-host:5432/restore_check latest.dump

psql postgres://app@restore-host:5432/restore_check \
  -c "select count(*) from orders where created_at > now() - interval '30 days';"

# record the outcome - date, duration, row counts, anything unexpected

Full lesson: Databases, object storage and backups →

Email, cron jobs and background workers

Transactional email

Records the provider will ask for

  MX      for the sending subdomain, if it has a dedicated return path
  SPF     include the provider on the sending domain
  DKIM    CNAMEs or TXT records with the public key
  DMARC   starting at p=none, with an aggregate report address
  CNAME   click and open tracking domains, if you enable them

Use a subdomain for sending, e.g. mail.example.com, so a reputation
problem does not affect the root domain.

Scheduled jobs

# crontab on a VPS: five fields, then the command
# minute hour day-of-month month day-of-week
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
[email protected]

0 3 * * *   /srv/app/bin/backup.sh >> /var/log/backup.log 2>&1
*/5 * * * * /srv/app/bin/worker-tick >> /var/log/worker.log 2>&1

Scheduled jobs

# a cron wrapper with a lock and a real exit path
#!/usr/bin/env bash
set -euo pipefail

exec 9>/var/lock/app-report.lock
flock -n 9 || { echo "already running"; exit 0; }

echo "start $(date -Is)"
/srv/app/bin/report --since "1 day ago"
echo "done $(date -Is)"

Full lesson: Email, cron jobs and background workers →

Monitoring, uptime and log management

Uptime checks and alerting

# an external check you can run from anywhere
curl -fsS -o /dev/null -w "%{http_code} %{time_total}s\n" https://example.com/readyz

# and one that exercises a real path
curl -fsS -o /dev/null -w "%{http_code} %{time_total}s\n" \
  "https://example.com/api/search?q=test"

Logs and error tracking

// structured logs: one JSON object per line, with the fields you will search on
logger.info({
  event: "order.created",
  orderId: order.id,
  customerId: order.customerId,
  amount: order.total,
  durationMs: Date.now() - started
});

// never log secrets, tokens or full personal data
logger.info({ event: "auth.login", userId: user.id, ip: req.ip });   // not the password, not the token

Full lesson: Monitoring, uptime and log management →

Scaling: load balancing, autoscaling and stateless design

Horizontal, vertical and stateless

State that breaks horizontal scaling

  sessions in a process's memory        -> move to a shared store or a signed cookie
  uploaded files on local disk           -> move to object storage
  in-process cache as the source of truth -> use it as a cache, not as a store
  a scheduled job in the web process      -> one scheduler, or a distributed lock
  local temp files between requests       -> no assumption survives with two instances

Balancing and autoscaling

# graceful removal: stop sending new requests, then wait for in-flight ones
# in nginx, the equivalent is a slow shutdown with keepalive drained
upstream app {
    server 10.0.1.11:3000 max_fails=3 fail_timeout=30s;
    server 10.0.1.12:3000 max_fails=3 fail_timeout=30s;
    keepalive 32;
}

Full lesson: Scaling: load balancing, autoscaling and stateless design →

Security hardening, cost control and migrations

Access and patch policy

# automated dependency and OS patching signals
npm audit --omit=dev --audit-level=high
docker scout cves registry.example/app:latest

# unattended security upgrades on a Debian-based host
# /etc/apt/apt.conf.d/20auto-upgrades
# APT::Periodic::Update-Package-Lists "1";
# APT::Periodic::Unattended-Upgrade "1";

Cost control and migrations

Migrating a live site between hosts

  1. inventory     every record, every cron job, every certificate, every integration
  2. lower TTLs    48 hours before any DNS change
  3. provision     the new environment and deploy the same artefact
  4. copy data     with a documented cutover point or continuous replication
  5. test          against the new environment by host header, not by the public name
  6. cut over      DNS, or the load balancer, in one change
  7. verify        resolution, TLS, email, payments, login, and the slowest page
  8. keep the old  running and unmodified for a week
  9. clean up      after the window, and only after a written sign-off

Full lesson: Security hardening, cost control and migrations →

FAQ

Is this Web Hosting cheat sheet free to use?
Yes. No sign-up and no tracking: the page is static, every example is on the page itself, and you can print it or save it as a one-page reference.
Where do the examples come from?
Every snippet is taken from the 12 lessons of the Web Hosting course on this site, and each section links back to the lesson it was pulled from.
How do I go deeper than a cheat sheet?
Open the full Web Hosting course — it carries the worked explanations, the edge cases and the exercises behind every line here.

SEO Basics Domains & DNS CDNs & Caching Accessibility

Last refreshed 2026-09-27.