The Fundamentals Worth Learning as a Software Engineer
The software engineering fundamentals that outlast every framework: how code runs, data structures, complexity, databases, networking, concurrency, Git, testing, reading code and writing, with how deep to go and where to learn each.
Jun 15, 202612 min read

The short answer: which software engineering fundamentals matter
Every few months someone asks me which framework to learn next, and my honest answer is that it matters less than they think. The software engineering fundamentals underneath the framework matter far more: how a computer runs your code, how data is stored and queried, how machines talk to each other, how to reason about cost and concurrency, and how to read, test and explain code. Frameworks are the fastest moving and least durable part of what you know. Fundamentals are the part that was true before your current stack existed and will still be true after it is replaced.
I am a Lead Full Stack Engineer, and the engineers I have seen stay useful across a decade are the ones who invested in that layer. This post is my list of it. It is deliberately short, because a list of forty things is a list nobody acts on, and for each item I say how deep you actually need to go and where to learn it.
Fundamentals vs frameworks: why the layer underneath wins
A framework is a set of decisions someone else made about the fundamentals. React makes decisions about rendering, an ORM makes decisions about SQL, a cloud service makes decisions about networking and storage. When everything works, you do not need to know what those decisions were. When something breaks, runs slowly or behaves strangely, you need to know exactly that.
That is the practical case for fundamentals. They are what you fall back on when the tool does something you did not expect, which it will. They also make every new framework faster to learn, because you recognise the underlying idea and only have to learn the new names for it.
1. How a computer actually runs your code
Not at the level of a computer architecture course. At the level where you can explain why your program is slow.
Know that reading from memory is far slower than the processor, which is why caches exist and why iterating an array beats chasing pointers through a linked list. Know what a process and a thread are, and that starting either is expensive. Know that disk is slower than memory by a margin most people underestimate, and that a network call is slower again.
The well known table of latency numbers every programmer should know, originally put together by Jeff Dean and Peter Norvig, gives rough orders of magnitude:
| Operation | Approximate time |
|---|---|
| L1 cache reference | 0.5 ns |
| Main memory reference | 100 ns |
| Read 4 KB randomly from an SSD | 150 µs |
| Round trip within the same data centre | 500 µs |
| Disk seek | 10 ms |
| Packet from California to the Netherlands and back | 150 ms |
You do not need these memorised, and hardware has moved on since they were first compiled. You need the ordering, because almost every performance decision is really a question of which layer you just accidentally touched. If you want to go deeper, the free OSTEP book (Operating Systems: Three Easy Pieces) and Nand2Tetris are both excellent.
2. Data structures, as a set of trade-offs
The mistake is learning these only as things to implement. Learn them as choices with costs.
An array gives fast indexed access and expensive insertion in the middle. A hash map gives constant time lookup on average, at the cost of memory and ordering. A tree keeps things sorted at logarithmic cost. A queue and a stack differ only in which end you take from, and that decides whether a traversal goes broad or deep.
When you choose how to store something, you are choosing which operation you want to be cheap. I wrote a whole post on that idea: choosing a data structure is choosing what to make cheap. If you learn better by seeing, VisuAlgo animates each structure step by step.
3. Complexity, at conversational depth
You should be able to look at a loop inside a loop and say "quadratic" without thinking, and notice when you have written one by accident by calling a function that loops inside another loop.
The more useful and less taught half is knowing when it does not matter. A quadratic algorithm over ten items is fine. Rewriting it into something clever and unreadable is a real cost paid for an imaginary gain. Complexity is a tool for spotting the case where your data grows and your code falls over, not a virtue to maximise. The DSA roadmap covers this in order if you want a structured path.
4. Database fundamentals: how data is stored and queried
Almost every application is a user interface wrapped around a database, and the database is where the hard problems live.
- Indexes. Know what an index is and why adding one makes reads faster and writes slower.
- Transactions. Know what a transaction guarantees, and specifically what happens when two of them touch the same row.
- SQL. Know enough to write a join and a group by without looking it up, because an ORM will eventually generate something terrible and you need to be able to read it.
- Schema design. Know why normalisation exists and when breaking it on purpose is correct.
And learn early that the schema is the hardest thing in your codebase to change later. Code can be rewritten; data cannot. Grokking Database Fundamentals for Tech Interviews is a clear introduction, Designing Data-Intensive Applications is the book to read once you have some experience, and the free CMU Database Systems lectures go as deep as you like.
5. Networking for developers: how machines talk to each other
The network is where a lot of your bugs will be, and many engineers treat it as a black box.
Know what happens between a request leaving your code and a response arriving. What DNS does. What a TCP connection costs to set up, and why keeping one open matters. Why HTTPS adds a handshake. What the difference is between a 4xx and a 5xx status code, and why that is the first thing anyone debugging asks. What a timeout actually does, and what a retry does to a system that is already struggling.
That last point is worth sitting with. Retries feel like resilience and are frequently how a small problem becomes an outage. Google's Site Reliability Engineering book says to always use randomised exponential backoff, to limit retries per request, and warns that retries stacked across layers can make an overloaded backend melt down. The free Computer Networking: A Top-Down Approach video lectures and Beej's Guide to Network Programming are good places to start.
6. Concurrency basics, at least conceptually
You may never write threaded code by hand. You will certainly write code where two things happen at once, because that is what a web server is.
- Race conditions. Two operations on the same data without coordination can interleave and produce a value neither of them wrote.
- Locks and deadlocks. A lock serialises access; holding two locks in an inconsistent order can deadlock.
- Async is not threads. An async function is not a thread, and awaiting inside a loop often serialises work you meant to run in parallel.
Grokking Multithreading and Concurrency for Coding Interviews covers these with concrete examples, and it is useful well beyond interviews.
7. Version control, properly
Not the three commands. The model.
Git stores snapshots, and a branch is a movable pointer to one of them. Once that sentence means something to you, merge, rebase, reset and cherry-pick stop being spells and become obvious operations on a graph. The practical dividend is that you can recover from almost anything, because Git rarely truly deletes a commit. I wrote the full version in Git, properly: the model behind the commands.
8. Testing, as a design tool
Most testing advice argues about coverage numbers, which is the least interesting part.
The useful insight is that code which is hard to test is usually badly designed, and the difficulty is the signal. A function that needs six mocks is telling you it does too much or reaches too far. Beyond that: test behaviour rather than implementation, so a refactor does not break fifty tests, and write the test that reproduces a bug before you fix it. My post on five kinds of API test and when each one earns its place goes further.
9. Reading code and debugging
You will read far more code than you write, most of it unfamiliar and some of it bad. Opening a large codebase and finding the relevant part without panicking is a trainable skill, and almost nobody trains it on purpose. Pick a project you use and read it. The question on how to read and understand a large codebase has a method.
Debugging is the same muscle pointed at a problem: form a hypothesis, test it, narrow down. If you reach for an AI tool before forming any hypothesis, you skip the part that builds the skill. I wrote about getting better at debugging without asking AI first.
10. Writing and explaining
This is the one people skip, and it decides how far they get.
The design document that gets agreed, the pull request description that gets reviewed quickly, the incident summary people actually understand: these determine whether your work counts, and they are all writing. An engineer who can explain a trade-off in three clear sentences has an advantage over a stronger engineer who cannot. See how to explain technical ideas to other engineers for practical habits.
How deep to go in software engineering fundamentals
You cannot learn all of this at once, and you should not try. Here is how I would sequence it depending on where you are:
| Fundamental | Student or fresher | Working engineer (1 to 3 years) | Where to start |
|---|---|---|---|
| How code runs | Orders of magnitude | Profiling real code | OSTEP |
| Data structures | Core set, by trade-off | Choosing under load | DSA roadmap |
| Complexity | Spot quadratic loops | Know when it does not matter | DSA cheat sheet |
| Databases | SQL, indexes, joins | Transactions, schema changes | Backend roadmap |
| Networking | HTTP, DNS, status codes | Timeouts, retries, TLS | Networking lectures above |
| Concurrency | Race conditions | Locks, async pitfalls | Concurrency course above |
| Git | Daily commands, the model | Recovery, clean history | Git post |
| Testing | Unit tests for your projects | Tests as design feedback | API testing post above |
| Reading code | One open source project | Unfamiliar codebases at work | Open source roadmap |
| Writing | Clear READMEs | Design docs, PR descriptions | Docs for Developers |
Take one row, spend a month on it, and notice how many unrelated problems get easier. Then take the next. If you want the bigger picture of how these fit into systems, Grokking System Design Fundamentals and my learning roadmap for system design are the natural next step once the first six rows feel solid.
What is deliberately not on this list
Specific frameworks. Cloud certifications. The tool your current team uses. Design patterns as a catalogue to memorise. All of these are worth learning when you need them, and few of them survive a decade unchanged. A handful of good books covers the durable layer better than any framework course.
This also applies if your university teaches older technologies. The fundamentals are exactly the part that does not go out of date, which is why a degree that feels behind the times is often more useful than it looks.
My honest read
Here is a quick test of whether you have the layer or only the surface. Take something you use every day, a web framework, a database client, your package manager, and ask what it is doing on your behalf. If the answer is a shrug, that is your next month.
Frameworks make you productive. Fundamentals make you useful when the framework does something you did not expect. In a market where AI tools write a lot of routine code, that second kind of usefulness is worth more than it used to be, not less.
Learn it on Sefism
- Programming roadmap and DSA roadmap
- Backend roadmap for databases, networking and APIs
- System design roadmap and the system design cheat sheet
- Grokking Database Fundamentals for Tech Interviews
- Grokking System Design Fundamentals
- The Missing Semester of Your CS Education for the tooling nobody teaches
FAQ
What are the fundamentals of software engineering?
How a computer runs code, data structures and complexity, databases, networking, concurrency, version control, testing, reading code and clear writing. These change slowly and make every framework easier to learn.
Should I learn fundamentals or frameworks first?
Learn enough of one framework to build something real, then deepen the fundamentals underneath it. Doing only theory leaves you unable to build; doing only frameworks leaves you stuck when they misbehave.
Do I need a computer science degree to learn these fundamentals?
No. Free material such as OSTEP, CS50 and university lecture series covers all of them. A degree helps with structure and pace, but plenty of engineers learn the fundamentals on their own.
How long does it take to learn software engineering fundamentals?
Enough to be useful takes months, not years, if you spend about a month on each area alongside building projects. Depth keeps growing for your whole career.
Are fundamentals still important with AI coding tools?
More than before. AI tools produce plausible code quickly, and fundamentals are how you judge whether that code is correct, fast and safe.
Ask your own question
If your situation is different from anything here, the career questions library has honest answers to the questions students and engineers ask me most.
Want a learning roadmap built around you, written answers to your own questions and a place to discuss your FYP? Create your free Sefism account. Members can also book a one to one session when they want to talk it through.
Stay in touch
- LinkedIn: where I share roadmaps, career advice and honest takes on hiring. Follow, or message me.
- X (Twitter): short practical thoughts on engineering and careers.
- Instagram: quick tips and a more personal side.
- Sefism Discord: meet other students and engineers working through the same job market and share what is working.
- Sefism on YouTube: walkthroughs and talks.
Comments (0)
Comments are closed for now.
No comments yet.