DevOps Lounge

One tip a day.

62 of them so far. Short enough to read while the build runs.

  • git commit --amend changes your most recent commit. Avoid amending a commit you have already pushed to a shared branch, because it rewrites history.
  • Use git switch -c new-branch to create a branch and move to it in one step.
  • git stash sets aside your uncommitted changes so you can switch tasks. git stash pop brings them back.
  • Lost a commit? git reflog lists where HEAD has been recently, so you can usually get it back.
  • git bisect uses a binary search through your history to find the commit that introduced a bug.
  • git log --oneline --graph --all gives you a quick visual map of your branches.
  • git diff --staged shows exactly what your next commit will contain.
  • git add -p lets you stage parts of a file, which helps keep each commit focused on one change.
  • Write commit messages that explain why a change was made. The diff already shows what changed.
  • Keep secrets out of Git. If one is ever committed, assume it is compromised and revoke it, even after you delete it from history.
  • Add a .gitignore before your first commit so build output and .env files never get tracked.
  • In the shell, Ctrl+R searches your command history. It saves a lot of retyping.
  • !! in Bash repeats your last command. sudo !! reruns it with sudo.
  • Quote your shell variables: "$file" rather than $file. Unquoted variables break on spaces.
  • Start Bash scripts with set -euo pipefail so they stop on errors, unset variables and failed pipes.
  • curl -I https://example.com fetches only the response headers, which is handy for checking redirects and caching.
  • ss -tulpn shows which processes are listening on which ports on Linux. It replaces the older netstat.
  • du -sh * | sort -h shows what is using disk space in the current folder, sorted by size.
  • tail -f app.log follows a log file live. journalctl -u myservice -f does the same for a systemd service.
  • chmod 777 is rarely the right fix. Find out which user needs access and give only that user what it needs.
  • Use SSH keys rather than passwords for your servers, then disable password login.
  • In Docker, copy your dependency manifest and install before you copy your source code. Layer caching will make rebuilds much faster.
  • Multi-stage Docker builds keep compilers and build tools out of your final image, so it is smaller and has less to attack.
  • Do not run containers as root unless you must. Add a USER instruction to your Dockerfile.
  • Pin your base images to a specific version. latest can change under you and break a build with no code change.
  • Add a .dockerignore file so node_modules, .git and secrets do not end up in your build context.
  • docker system df shows how much space images, containers and volumes use. docker system prune removes unused data, so read its warning first.
  • In Kubernetes, set resource requests and limits on your containers so one workload cannot starve the others.
  • A liveness probe restarts a stuck container. A readiness probe stops traffic until the container is ready. They solve different problems.
  • kubectl describe pod <name> is usually the first step in debugging. Its Events section often tells you exactly what went wrong.
  • Make your CI fail fast: run linting and unit tests before slower integration tests and builds.
  • Treat your infrastructure like code: keep it in version control and review changes like any other pull request.
  • Deploys should be boring. Small, frequent releases are easier to review, debug and roll back than big ones.
  • Practice restoring your backups. A backup you have never restored is only a hope.
  • Alert on symptoms users feel, like errors and slow responses, rather than on every internal metric.
  • Structured logs (such as JSON) are far easier to search and filter than free-form text.
  • Log enough to debug a problem, but never log passwords, tokens or personal data.
  • Always use parameterized queries for SQL. Building queries by joining strings invites SQL injection.
  • Store passwords with a slow password hash such as Argon2 or bcrypt. Never store them in plain text, and do not use a fast hash like MD5 or SHA-256 alone.
  • Validate input on the server, even if you already validate it in the browser. Client-side checks can be bypassed.
  • Run npm audit, pip-audit or your language's equivalent regularly to find dependencies with known vulnerabilities.
  • Add an index for columns you filter on often, and use EXPLAIN to confirm your query actually uses it.
  • An N+1 query problem happens when you run one query per row in a loop. Fetch the related data in one query instead.
  • Wrap related database writes in a transaction, so they either all succeed or all fail together.
  • Use <button> for actions and <a> for navigation. You get keyboard support and accessibility for free.
  • Every meaningful image needs useful alt text. Purely decorative images should use an empty alt="".
  • CSS gap works with both flexbox and grid. It is often simpler than adding margins to each child.
  • Open the browser's Network tab before guessing. It shows the exact request, response and timing.
  • Use const by default in JavaScript. Use let only when a value really needs to change.
  • await in a loop runs tasks one at a time. Use Promise.all when they can safely run at the same time.
  • In Python, use a virtual environment per project: python -m venv .venv. It keeps dependencies from clashing.
  • In Python, avoid a mutable default argument such as def f(items=[]). The same list is shared across calls. Use None instead.
  • Read the whole error message from the top, especially the first line that mentions your code. It usually says more than it first seems.
  • When you are stuck, write the smallest example that reproduces the bug. You will often find the cause while doing it.
  • Explain your bug out loud to someone, or to a rubber duck. Saying it step by step often exposes the wrong assumption.
  • Change one thing at a time when debugging. If you change five things, you will not know which one mattered.
  • A failing test is the best way to start fixing a bug. It proves the bug exists and shows when it is gone.
  • Test behaviour rather than implementation details, so your tests still pass when you refactor.
  • Name things for what they mean, not how they work. Good names can replace a lot of comments.
  • Comments should explain why the code does something surprising. The code itself should show what it does.
  • Read other people's code. Picking one open-source project and following how it works teaches things tutorials cannot.
  • Take breaks. Many hard bugs get solved on a walk, once your brain stops repeating the same wrong idea.

Pull up a chair

Join, pick your language and what you work on, and say hi. It takes a minute.

Join on Discord