Core developer skills
The skills every developer leans on, whatever the stack: version control, the terminal, containers, databases, testing, security and the career side of the job.
Git 7
-
Git Mistake First Aid: Plain-English Recovery Recipes
A short, no-jargon page of recipes for the Git situations that make people panic: committed to the wrong branch, a bad commit message, an undo that went too far. Bookmark it, then read the explanations so the fix stops feeling like magic.
dangitgit.comGitBeginner -
Atlassian Git Tutorials: Workflows, Merging and Rewriting History
Free, well-illustrated tutorials that go beyond commit and push: branching workflows, merge versus rebase, undoing changes and rewriting history. A good second Git resource once the basics are comfortable and you start working in a team.
atlassian.comGitBeginner -
Undo the Undo: Recovering Lost Commits With git reflog
Git rarely deletes work right away. Every time HEAD or a branch tip moves, the reflog records where it was, so a botched reset or rebase is usually recoverable. Read entries like
HEAD@{3}as "where HEAD was three moves ago". Create a branch from the right one before doing anything else, because a branch name is what keeps commits safe from cleanup. Two limits worth knowing: the reflog is local to your clone, and entries expire. By default unreachable ones are pruned after about 30 days and reachable ones after about 90, controlled bygc.reflogExpireandgc.reflogExpireUnreachable. So recover soon, and never rely on it as a backup.
git-scm.comGitIntermediate -
Challenge: Rescue a Branch You Just Deleted
Ten minutes, a scratch repo, no risk. Prove to yourself that a deleted branch is not gone. Now recover it: 1. Run
git reflogand find the "add payments" commit. 2. Rungit branch feature/payments <sha>with that hash. 3. Check withgit log feature/payments --onelineand confirmpay.txtexists after switching. Stretch goal: repeat the exercise, but this time lose the commit by runninggit reset --hard HEAD~1on the branch itself, and recover it the same way. Notice that the capital D in-Donly means "delete even if unmerged"; the commits stay in the object store until garbage collection removes them.
git-scm.comGitBeginner -
Interactive Rebase: Tidy a Branch Before Asking for Review
A reviewer reads your history as a story, so make it readable. Interactive rebase lets you reshape local commits before they are shared. In the editor, change the word at the start of a line: -
rewordto fix a message -squashorfixupto fold a commit into the one above it -dropto remove it, and reorder lines to reorder commits A neat habit: when you spot a fix for an earlier commit, record it withgit commit --fixup <sha>, then later rungit rebase -i --autosquash origin/mainand Git arranges the fixup commits for you. Rewriting changes commit hashes, so only do it on commits nobody else has based work on. If you must update a branch you already pushed, prefergit push --force-with-leaseover--force, because it refuses to overwrite commits you have not seen. If the rebase goes wrong,git rebase --abortrestores where you started.
git-scm.comGitIntermediate -
Find the Commit That Broke It: Automated git bisect
When a regression appeared "sometime in the last 200 commits", binary search beats reading diffs. Git bisect halves the range each step, so even a few hundred commits take around eight checks. The script passed to
rundecides the verdict by exit code: 0 means good, 1 to 127 (except 125) means bad, and 125 means "cannot test this commit, skip it". A script can be as small as a single test command, for examplenpm test -- -t "login"or acurlthat fails on a bad status. Tips: keep the script outside the repository tree or untracked so checkouts do not remove it, and make sure the build step is inside the script. Finish withgit bisect resetto return to your branch.
git-scm.comGitIntermediate -
Scrub a Leaked File From History With git filter-repo
If a credentials file or a huge binary landed in history, deleting it in a new commit does not remove it from old ones. The maintained tool for rewriting history is
git filter-repo, which the Git project itself points to in place offilter-branch. Notes: - It insists on a fresh clone as a safety check, so work on a copy. - Every commit after the file's first appearance gets a new hash, so every collaborator must re-clone or carefully reset, and open pull requests will need attention. - Forks, caches and CI logs may still hold the old data, and hosting platforms can keep unreachable commits for a while. The key point for secrets: assume they are compromised the moment they are pushed. Rotate the credential first; the history rewrite is cleanup, not remediation.
github.comGitAdvanced
Linux 7
-
Linux Journey: A Gentle Path From First Command to Confident User
Free lessons in small chunks covering the command line, users and permissions, processes, networking and more. Start here if the terminal still feels foreign, and use the quizzes to check what actually stuck before moving on.
linuxjourney.comLinuxBeginner -
explainshell: Paste a Command, See What Every Part Means
Paste any shell command and each flag and argument is matched to the relevant excerpt from its manual page. Handy for decoding a copied one-liner before you run it, and for learning how pipes and options fit together.
explainshell.comLinuxBeginner -
BashPitfalls: The Shell Mistakes Everyone Makes Once
A catalogue of common Bash bugs, each with a short explanation and a safer pattern: unquoted variables, parsing ls output, misuse of test. Read it before writing scripts that will run unattended, then run ShellCheck on what you have.
mywiki.wooledge.orgLinuxIntermediate -
Challenge: Find What Is Filling the Disk in Five Minutes
A full disk takes services down quietly, so practice the hunt before you need it. 1. Check which filesystem is full:
df -h2. Check inodes too, since many tiny files can exhaust them with space to spare:df -i3. Descend one level at a time: Repeat on the largest directory until you reach the culprit. The-xflag keepsduon one filesystem, andsort -hunderstands sizes like 4.0K and 2.1G. Your task: run this on your own machine or a VM, write down the three biggest directories under/var, and explain what each one is for. Bonus: a deleted file that a process still holds open keeps using space. Look for it withsudo lsof +L1, which lists open files whose link count is zero.
man7.orgLinuxBeginner -
Inspect a Running Process Through /proc
Linux exposes live process state as files, so you can answer many "what is this thing doing?" questions with
catandls, even on a minimal container image without extra tools. The command line is NUL-separated, hence thetr. A growing count infdpoints to a descriptor leak, andMax open filesinlimitstells you how close you are to the ceiling.VmRSSis resident memory. You can read your own processes freely; other users' details need root. The manual page above documents every file, and is worth skimming once formaps,smapsandenviron.
man7.orgLinuxIntermediate -
Make Bash Scripts Fail Loudly: set -euo pipefail Explained
A script that keeps going after an error can do real damage. A common opening is: -
-eexits when a command fails --utreats an unset variable as an error, catching typos like$DIR_NAEM--o pipefailmakes a pipeline fail if any stage fails, not just the last Know the limits.-eis ignored in places such as anifcondition or the left side of&&and||, and in a few subshell cases, so it is a safety net, not a substitute for checking results you care about. Tolerate an expected failure explicitly:grep -q foo file || true. Also quote your variables, and run ShellCheck. The manual page linked here lists every option precisely, including the exceptions to-e.
gnu.orgLinuxIntermediate -
Trace a Hung Process With strace
When a process is stuck and the logs are silent, strace shows what it asks the kernel to do. A blocked
readon a socket, aconnectto the wrong address, or endlessopenfailures all stand out. Meaning of the flags:-ffollows child threads and processes,-ttadds timestamps,-Tshows time spent inside each call,-slengthens printed strings, and-owrites to a file. Filtering with-e trace=cuts the noise. Read the last lines first: if the final line is a call that has not returned, that is where it is stuck. Expect a slowdown while tracing, and attaching may need root or relaxed ptrace settings. Avoid tracing a busy production process for long.
man7.orgLinuxAdvanced
SQL 5
-
Use The Index, Luke: A Free Book on SQL Indexing
A free online guide to how database indexes work and how to design them for real queries. It covers the anatomy of an index, the WHERE clause, sorting and joins. Read it when queries are slow and you want to understand why.
use-the-index-luke.comSQLIntermediate -
PostgreSQL Exercises: Practice SQL Against a Real Database
Graded SQL exercises on a small club-membership schema, running in the browser with hints and worked answers. Moves from simple selects to joins, aggregates and window functions, so it is a good place to practice after a first course.
pgexercises.comSQLBeginner -
Read a Postgres Query Plan Without Guessing
The plan tells you what the database did, so you can stop guessing at indexes. What to look for: - The scan type:
Seq Scanreads the whole table,Index ScanandBitmap Heap Scanuse an index. - Estimated versus actual rows. A big gap means stale statistics (runANALYZE) or a misleading predicate. -Rows Removed by Filter: many rows read and thrown away suggests a missing or wrong index. - Timing is per node and may be multiplied by the loop count. Important:ANALYZEreally executes the statement. For writes, wrap it:BEGIN; EXPLAIN ANALYZE UPDATE ...; ROLLBACK;. And a sequential scan on a small table is often the right choice, so judge by timing, not by the node name alone.
postgresql.orgSQLIntermediate -
Challenge: Fix a Slow Query With the Right Composite Index
Build a million-row table, watch a query struggle, then fix it. About twenty minutes in PostgreSQL. Compare the plans and timings. The index lets the database jump to one customer and read rows already in date order, so no sorting is needed. Then experiment: drop it and create
(created_at, customer_id)instead. Why is the first query worse now? Multicolumn B-tree indexes are most useful when the query constrains the leading columns, so put equality columns first, then the sort or range column.
postgresql.orgSQLIntermediate -
Isolation Levels in Plain Terms: Pick One on Purpose
Transactions are not automatically safe from each other. In PostgreSQL the default is Read Committed: each statement sees data committed before it started, so two reads in one transaction can differ. A classic bug is read-modify-write: Your options, roughly from lightest to strongest: an atomic UPDATE like the one above,
SELECT ... FOR UPDATEto lock the row, or a stricter level such as Repeatable Read or Serializable. The catch with the strict levels: the database may abort a transaction with a serialization failure (SQLSTATE 40001), and your code must retry the whole transaction. In PostgreSQL, Read Uncommitted behaves like Read Committed. Other databases differ, so check yours.
postgresql.orgSQLAdvanced
APIs 5
-
Learn OpenAPI: The Official Introduction to Describing APIs
The official learning site from the OpenAPI Initiative explains how to describe an HTTP API in a machine-readable contract. Start here before generating docs, mocks or client code, so the spec becomes the shared source of truth for the team.
learn.openapis.orgAPIsBeginner -
Microsoft Web API Design Best Practices: A Practical Checklist
A thorough guide to designing HTTP APIs: resource naming, methods and status codes, pagination, versioning and async operations. Useful as a review checklist for a new API, whatever stack or cloud you build on.
learn.microsoft.comAPIsIntermediate -
Idempotency Keys: Make Retried POST Requests Safe
Networks drop responses, not just requests. If a client retries a payment after a timeout, you must not charge twice. The standard fix is a client-generated idempotency key. Stripe documents a good reference design: the client sends an
Idempotency-Keyheader with a random value such as a UUID (their keys can be up to 255 characters), and the server stores the first result and replays it for retries. Reusing a key with different parameters is rejected. A minimal server-side shape: 1. Insert the key before doing work. A unique violation means it is a retry or a concurrent duplicate. 2. If the stored hash differs from this request, return an error. 3. Run the operation and save the response in the same transaction where possible. 4. Expire old keys; Stripe prunes after at least 24 hours. GET and DELETE are already idempotent by definition, so keys matter mainly for POST.
docs.stripe.comAPIsIntermediate -
Challenge: Replace Offset Pagination With a Keyset Cursor
OFFSET pagination gets slower the deeper you go, and it can skip or repeat rows when data changes between pages. Keyset pagination fixes both. Try it in thirty minutes on any SQL database with a table of a few hundred thousand rows. Page one: Next page, using the last row you returned: Steps: 1. Create an index on
(created_at, id). 2. CompareEXPLAINoutput for this query againstOFFSET 100000. 3. Encode(created_at, id)as an opaque base64 string and return it asnext_cursorin your API response. The tie-breakeridmatters because timestamps repeat. The trade-off: you lose jump-to-page-N, which is usually fine for feeds and exports.
use-the-index-luke.comAPIsIntermediate -
Change an API Without Breaking Anyone: Compatibility Rules
Clients you do not control will depend on every detail you expose. Google's API improvement proposal on backwards compatibility spells out what is safe within one major version. Generally safe: adding new methods, new response fields, and optional request fields whose default preserves old behavior. Adding enum values to responses is allowed but risky, since clients may not handle unknown values, so document it. Breaking: removing anything, renaming (which is removal plus addition), changing a field's type, changing a default, changing a value's format, or tightening semantics that clients rely on. Habits that follow: - Make new request fields optional. - Tell clients to ignore unknown response fields and handle unknown enum values. - To rename, add the new name, keep the old one, deprecate it publicly, and remove it only in a new major version. - Review diffs of your OpenAPI file in CI to catch accidental breaks. When a break is truly necessary, version it and give people time to migrate.
google.aip.devAPIsAdvanced
Docker 4
-
Docker Build Best Practices: Smaller, Faster, Safer Images
The official guidance on writing Dockerfiles: choosing base images, multi-stage builds, layer caching, pinning and cleanup. Use it as a review checklist the next time an image feels bloated or a build keeps missing the cache.
docs.docker.comDockerIntermediate -
iximiuz Labs: Hands-On Container and Linux Playgrounds
Browser-based playgrounds and challenges for containers, Linux internals and Kubernetes, with a number of free ones. Good for building a real mental model of what a container is, by poking at namespaces and cgroups yourself.
labs.iximiuz.comDockerIntermediate -
Multi-Stage Docker Builds: Ship the Binary, Not the Toolchain
Build tools, caches and source code have no business in your runtime image. A multi-stage build compiles in one stage and copies only the result into a small final one. Results: a much smaller image, a smaller attack surface, and faster pulls. Copying the dependency files before the source keeps the download layer cached until they change. Caveats:
scratchhas no shell, CA certificates or timezone data, so copy those in or choose a minimal base such as a distroless one if you need them. Interpreted languages follow the same idea: install dependencies in a builder stage and copy the prepared directory over. You can also stop at a stage withdocker build --target build .to debug it.
docs.docker.comDockerIntermediate -
Challenge: Lock Down a Container and Prove It Worked
Run a container with fewer privileges, then verify each restriction yourself. Needs Docker and about fifteen minutes. Inside the container, test: 1.
idshould show uid 10001, not root. 2.touch /xshould fail with a read-only filesystem error, whiletouch /tmp/xsucceeds. 3.grep CapEff /proc/self/statusshould show all zeros, meaning no effective capabilities. Now loosen one flag at a time and notice what changes. Then ask the harder question for your own service: which flags does it actually need, and what breaks when you remove the rest? Put the result into a Compose file or Kubernetes security context so it is repeatable. Never use--privilegedas a shortcut to make an error disappear.
docs.docker.comDockerIntermediate
System Design 4
-
System Design Primer: A Map of Scaling Concepts and Trade-offs
A large open-source study guide covering load balancers, caching, databases, queues and consistency, with diagrams and example designs. Use it to build vocabulary and a mental catalogue of trade-offs before design discussions or interviews.
github.comSystem DesignIntermediate -
Amazon Builders Library: How Large Systems Fail and Recover
Articles by Amazon engineers on operating distributed systems, including timeouts, retries with backoff and jitter, and avoiding overload. Read them when you design for failure and want the reasoning behind patterns, not only the names.
aws.amazon.comSystem DesignAdvanced -
Cache-Aside Done Right: TTLs, Invalidation and Stampedes
Cache-aside is the usual pattern: the application checks the cache, falls back to the database on a miss, and fills the cache itself. Points to get right: - Always set a TTL, so mistakes eventually heal. Add jitter so many keys do not expire together. - On writes, update the database first and then delete the key. Deleting is simpler than rewriting. - A hot key expiring can send many requests to the database at once. Let one request rebuild it while the others wait or serve slightly stale data. - Decide whether caching "not found" is worth it, with a short TTL. Remember the cache is an optimization; the system must still work, slowly, without it.
learn.microsoft.comSystem DesignIntermediate -
At-Least-Once Queues Need Idempotent Consumers
Most queues promise at-least-once delivery. A message can arrive twice, so a consumer that is not safe to repeat will eventually bill someone twice. Take SQS as a concrete example. A received message becomes invisible for the visibility timeout (default 30 seconds). If you do not delete it in time, it reappears and another consumer may process it. You can extend it with
ChangeMessageVisibility, up to a 12-hour total limit. Safe consumer recipe: 1. Pick a stable id: the message id or, better, a business id such as an order number. 2. In one database transaction, insert that id into aprocessedtable with a unique constraint and apply the effect. 3. If the insert conflicts, skip the work. 4. Delete the message only after the transaction commits. 5. Set the timeout above your typical processing time, and configure a dead-letter queue so poison messages stop looping. Alert on dead-letter queue depth and on message age, since those show trouble before users do.
docs.aws.amazon.comSystem DesignAdvanced
Testing 4
-
The Practical Test Pyramid: Deciding What to Test Where
A long, example-driven article on balancing unit, integration, contract and end-to-end tests. Read it when your suite is slow or flaky, or when you cannot decide at which level a new test belongs.
martinfowler.comTestingIntermediate -
Software Engineering at Google: The Testing Overview Chapter
A free chapter on why tests matter at scale, how test size relates to speed and reliability, and what makes tests maintainable. A good grounding for arguing about test strategy with evidence rather than taste.
abseil.ioTestingIntermediate -
Challenge: Test Your Code With Properties, Not Just Examples
Example-based tests check what you thought of. Property-based tests check rules and let the library hunt for counterexamples. Try it in twenty minutes with Python. Run
pytest. Now pick a function of your own and write a round-trip property, such asdecode(encode(x)) == x. When a property fails, Hypothesis shrinks the input to a small failing example, which is often the real lesson. If it fails on something you consider invalid input, tighten the strategy and write down the assumption. Good property candidates: round trips, idempotence, "output is never longer than input", and comparing a fast implementation to a simple one.
hypothesis.readthedocs.ioTestingIntermediate -
Test Behavior, Not Implementation: Guiding Principles for UI Tests
Tests that break on every refactor teach teams to ignore them. The Testing Library project argues for tests that resemble how people use the software, because that is where confidence comes from. Practical consequences, in any stack: - Query elements the way a user finds them: by role, label or visible text, not by CSS class or internal component names. - Assert on outcomes a user can see, such as a message appearing, not on state variables or method calls. - Avoid testing private helpers directly. If a refactor changes internals but not behavior, the test should still pass. - Mock at the network boundary, not inside your own modules. A quick self-check for any test: if I rename an internal function, does it fail? If yes, it is coupled to implementation. If I break the feature, does it fail? If no, it is not protecting anything. Use a few end-to-end tests for critical journeys and let faster, focused tests cover the rest.
testing-library.comTestingBeginner
Security 4
-
OWASP Top 10: The Standard Awareness List for Web Risks
The widely referenced list of the most critical web application security risks, with explanations and prevention advice for each. Use it as a shared vocabulary for reviews and threat conversations, and as a map of what to study next.
owasp.orgSecurityBeginner -
Hacksplaining: Interactive Lessons on How Attacks Work
Short, free, interactive lessons that walk through attacks such as SQL injection and cross-site scripting, then show how to prevent them in code. A friendly way to see the attacker view before you dig into deeper labs.
hacksplaining.comSecurityBeginner -
Broken Access Control: Stop Users Reading Each Other's Data
In the 2021 edition of the OWASP Top 10 this category ranked first, and the common form is simple: change an id in a URL and see someone else's record. Here
$2comes from the authenticated session, never from the request. Habits that prevent most cases: - Deny by default; require an explicit permission check on every endpoint. - Enforce authorization on the server for every request. Hiding a button is not access control. - Centralize checks in one policy layer instead of scattering ad hoc ifs. - Prefer unguessable ids as defense in depth, not as the only defense. - Write tests that log in as user A and request user B's resources, expecting 403 or 404. Log denied attempts and alert on bursts of them.
owasp.orgSecurityBeginner -
Challenge: Break and Fix a Query With SQL Injection
Run this on your own machine, in a throwaway file, to see the attack and the fix side by side. About ten minutes with Python. The first query lets input rewrite the SQL. In the second, the driver sends the value separately from the statement, so it can only ever be data. Your tasks: 1. Predict the output before running. 2. Find one place in a project of yours that builds SQL by concatenation and convert it. 3. Handle what placeholders cannot: table names, column names and ORDER BY direction. Check those against a fixed allowlist in code. ORMs help but still allow raw string fragments, so review those too.
owasp.orgSecurityBeginner
Cloud 4
-
AWS Well-Architected Framework: A Review Lens for Cloud Designs
A set of questions and best practices across areas like security, reliability, cost and operations. Even outside AWS it is a handy checklist for design reviews, and the questions are free to read without an account.
aws.amazon.comCloudIntermediate -
Microsoft Learn: Free Cloud Fundamentals and Role-Based Paths
Free, structured modules and learning paths on cloud concepts, networking, identity and DevOps, many with sandbox environments. A solid starting point if you want guided practice instead of piecing docs together alone.
learn.microsoft.comCloudBeginner -
IAM Least Privilege: Grant What the Job Needs, Nothing More
Broad permissions turn a small leak into a big incident. The AWS IAM best-practices guide is worth reading even if you use another cloud, because the ideas transfer. Core habits: prefer temporary credentials (roles) over long-lived access keys, require MFA for people, remove unused identities, and start narrow. A scoped policy, read access to one prefix in one bucket: How to get there in practice: begin with the smallest policy you can, test, and add what is denied. IAM Access Analyzer can help by generating a policy from recorded activity and by flagging resources shared outside your account. Remember that an explicit deny always wins over an allow, and avoid wildcards in both actions and resources unless you can justify them. Review roles on a schedule; permissions only ever grow unless someone prunes them.
docs.aws.amazon.comCloudIntermediate -
Challenge: Audit Your Cloud Account for Public Storage
Accidentally public buckets are a classic cloud leak. Spend fifteen minutes checking an AWS account you own, using read-only commands. (Other clouds have equivalents; the habit is the point.) How to read the results: -
get-public-access-blockshows whether the four Block Public Access settings are on. An error saying no configuration exists means that bucket has none. -get-bucket-policy-statusreportsIsPublicfor the bucket policy. - Also check the account-level setting withaws s3control get-public-access-block --account-id <id>. Your tasks: list every bucket that is not fully blocked, write down why each should be public (usually none should), and plan to enable Block Public Access at the account level. Serve public websites through a CDN instead of opening buckets. Do not change anything until you know which application depends on it.
docs.aws.amazon.comCloudBeginner
Debugging 3
-
Brendan Gregg on Linux Performance: Tools Mapped to the Stack
A reference page that maps observability and tracing tools to the parts of a Linux system they inspect, with diagrams and talks. Reach for it when a box is slow and you need to know which tool answers which question.
brendangregg.comDebuggingAdvanced -
The USE Method: A Checklist for Finding Bottlenecks
A simple method for performance problems: for every resource, check utilization, saturation and errors. It gives you a systematic order of questions instead of guessing, and applies to CPUs, disks, networks and queues alike.
brendangregg.comDebuggingAdvanced -
Debug Production With Logs, Metrics and Traces: Start With a Question
Production debugging goes faster when you pick the right signal. Roughly: metrics say that something is wrong, traces say where in the request path, and logs say why. A workable sequence: 1. State the symptom as a measurable question: "p95 latency of checkout rose after 14:00". 2. Use metrics to scope it: which service, endpoint, region, version? 3. Open a slow trace to find the span that takes the time. 4. Search logs for that request id to read the detail. This only works if you prepared. Emit structured logs (JSON with fields) and include a request or trace id in every line, and pass it across service calls. Keep metric labels low-cardinality, so avoid user ids as labels. Then form one hypothesis at a time and test it with a query, instead of changing things. The OpenTelemetry primer linked here explains the vocabulary of signals, context propagation and instrumentation clearly.
opentelemetry.ioDebuggingIntermediate
Career 3
-
Tech Interview Handbook: Resume, Coding and Behavioral Prep
A free, curated handbook on the whole job search: resumes, preparing for coding rounds, behavioral questions and negotiation. Use it as a single organized starting point, then dive into the sections that match your stage.
techinterviewhandbook.orgCareerBeginner -
StaffEng Guides: Growing Beyond Senior Engineer
Practical guides on technical leadership at senior levels: scope, influence, working with leadership and writing for decisions. Helpful even earlier, since it shows which habits you can start building now.
staffeng.comCareerAdvanced -
Resume Basics: One Page That Survives a Quick Skim
A recruiter or engineer may spend under a minute on a first pass, so optimize for scanning. Structure: contact line, short experience entries in reverse chronological order, projects, education, skills. Keep it to one page when you have under roughly a decade of experience. Write each bullet as action, what you did, and the result: Only use numbers you can defend in an interview; if you cannot measure it, describe the visible outcome honestly. Lead with the technologies that matter for the role, drop the ones you would not want to be quizzed on, and skip photos, rating bars and long objective statements. Practical checks: export to PDF, make the text selectable, use a standard font, and ask a friend to circle the first three things they remember. Tailor the top third for each application.
techinterviewhandbook.orgCareerBeginner
Soft Skills 3
-
Google Technical Writing Courses: Clearer Docs, Issues and Emails
Free, short courses on writing clear technical prose: precise words, active voice, organizing documents and reviewing drafts. Useful for design docs, pull request descriptions and any message that others must act on.
developers.google.comSoft SkillsBeginner -
Code Review That Helps: Habits for Authors and Reviewers
Google's public engineering practices describe a simple standard: approve a change once it improves the overall health of the codebase, even if it is not how you would have written it. Perfect is not the bar. For authors: - Keep changes small and focused; they get reviewed faster and more carefully. - Write a description that says what and why, and link the issue. - Review your own diff first and run the tests. For reviewers: - Look at design, correctness, tests, naming and readability, roughly in that order of importance. - Prefix minor preferences with "Nit:" so the author knows they are optional. - Explain why, and ask questions before assuming a mistake. - Respond promptly. Waiting for review is the biggest cost to the author. Disagreement tip: when stuck in a loop, move to a call or a short design chat, then write the outcome in the thread. Comment on the code, never on the person.
google.github.ioSoft SkillsIntermediate -
Write a Design Doc That Surfaces Trade-offs Early
A design doc is for finding problems while changes are still cheap. It is worth writing when a design is ambiguous or the choice involves real trade-offs, and not worth it when it would only describe obvious implementation. A useful outline: 1. Context and scope: what this is and why now. 2. Goals and non-goals: non-goals prevent argument about things you never meant to solve. 3. The design: overview first, then APIs, data storage and key flows, with a diagram. 4. Alternatives considered, and why each lost. 5. Cross-cutting concerns: security, privacy, observability, rollout. Keep it short for small work; a page or two is fine. Large projects naturally run longer, but split anything that sprawls. Before sending, ask: could a reader tell what decision I want from them? Put that at the top, name reviewers, and set a date for comments. Record the final decision in the doc so it remains useful later.
industrialempathy.comSoft SkillsIntermediate
Interviews 2
-
NeetCode Roadmap: A Structured Path Through Coding Problems
A free roadmap that groups algorithm problems by pattern, such as two pointers, graphs and dynamic programming, with a visual map of dependencies. Handy for turning random practice into a deliberate plan for coding interviews.
neetcode.ioInterviewsIntermediate -
Behavioral Interviews: Build a Story Bank Before You Need It
Behavioral questions test judgment and teamwork. Prepare, because improvised stories ramble. A reliable shape is STAR: Situation, Task, Action, Result. Spend most of your time on Action and Result, and say "I" for what you did and "we" for what the team did. Build a bank of four or five real stories from your work, studies or projects, and tag each with themes: - a conflict or disagreement you worked through - a failure and what changed afterward - a tight deadline or trade-off - leading or helping without authority - something you learned quickly Write each as bullet points, not a script, then practice aloud and time it to about two minutes. Prepare the follow-ups too: what would you do differently, and what did you measure? Use only experiences that really happened. Interviewers probe details and inconsistencies show quickly. Finish with a result and a lesson, and close the loop if asked.
techinterviewhandbook.orgInterviewsBeginner
More from the Vault
Talk it through with people who use these
Ask about any of these in the server, share what you build with them, and get new picks every day.
online now · members