Writing
Good Engineering Teams Don’t Expect Everyone to Know Everything
Experience should change what we expect from an engineer. It shouldn’t excuse unclear tickets, oversized pull requests or decisions that live in one person’s head.
By Ka Lun Chan · Engineering leadership · Leadership / Delivery
What should we reasonably expect from each other?
After more than 20 years in software engineering, writing code and leading engineering teams, there’s one question I keep coming back to: what should we reasonably expect from other people, when everyone has a different level of experience, a different technical background and a different amount of knowledge about the system?
Should a senior developer know everything about the codebase? Should someone six months into a project remember every technical decision? Should a junior developer be able to investigate an unfamiliar system without help? And if something seems obvious to me, should I expect it to be obvious to everyone else?
The answer changes with the person and the situation. What doesn’t change is this: we shouldn’t make understanding the work harder than the work itself. That’s why I push for smaller pull requests, smaller stories, clearer acceptance criteria and more precise communication. I want people spending less time working out what someone meant and more time solving the actual problem.
Just because I know something doesn’t mean everyone does
I’ve worked with engineering teams across countries, time zones and technical backgrounds. Some developers specialize in the frontend. Others are stronger in backend systems, databases, infrastructure or security. Even within one framework, people have had different experiences, and that’s normal.
I’ve worked with Python, Django, React, PostgreSQL and AWS for years, and I still look up syntax. Sometimes I forget a Django ORM expression, or a PostgreSQL JSON operation, or a Docker command I haven’t used in months. I know what I’m trying to accomplish. I don’t always remember how to write it. So why would I expect someone else to remember everything? I wrote about this in you don’t need to remember everything, and it applies just as much to a codebase as to syntax.
Even the person who wrote the code six months ago might not remember why they made a particular decision. I’ve looked at my own code from years ago and wondered what I was thinking. Now imagine being someone who just joined the team, or who normally works on a completely different part of the application. How are they supposed to know? I try to remind myself of that whenever I review someone’s work or talk through a problem with them.
Experience matters, and no two experiences are the same
Hiring, mentoring and leading developers taught me that years of experience don’t tell the whole story. Two developers might both have ten years. One spent them on a single application and knows its architecture and business rules deeply. The other moved across companies, frameworks and systems. Both bring something, and their strengths differ.
A developer with ten years of backend experience might have very little exposure to the frontend. Someone excellent with React might never have written a complex PostgreSQL query. Neither is a weak engineer. They’ve had different opportunities to learn. (The case for building some breadth anyway is in specialization shouldn’t stop at your own code.)
When I assign work, I think about what someone knows, what they haven’t been exposed to, and what they can figure out. Sometimes I give a task to the person who can finish it quickly. Sometimes I give it to someone because I want them to learn it. Those are two different expectations, and they start before the person is even on the team: what we think we learned about someone in an interview shapes what we expect from them later, often unfairly. If I’m handing someone a chance to learn, I shouldn’t expect the speed of someone who has done it twenty times. I do still expect them to take ownership, investigate, ask questions and make progress. Not knowing something is understandable. Not making an effort to figure it out is a different issue.
Experience should change expectations, not replace clarity
I expect more independence from a senior engineer than from a junior one. A senior engineer should be better at breaking down problems, recognizing risks, investigating unfamiliar code and making technical decisions. They should also know when to ask. I don’t expect them to know everything. Even a very experienced engineer can’t know a business rule nobody explained or a decision nobody documented.
I’ve heard “they’re a senior engineer, they should know this” plenty of times. Sometimes it’s fair. Sometimes we’re asking experience to make up for missing information. Did we explain the business requirements? Did we document the decision? Were the acceptance criteria clear? Did they have access to the right information? Or are we assuming they should work it all out because of their title?
A challenging problem helps people grow. An unclear problem with not enough context wastes their time. Experience helps people handle ambiguity. It isn’t a license to create ambiguity that didn’t need to exist. Turning ambiguity into work people can actually execute is part of how I lead.
Smaller pull requests make everyone’s life easier
I’ve seen pull requests with thousands of changed lines. Sometimes they’re unavoidable. More often they come from trying to do too much at once. A developer starts on a feature, notices something that needs refactoring, updates a few dependencies, cleans up some unrelated code, and by the time the PR is ready it holds five different kinds of change. Now someone has to review all of it, and that reviewer probably doesn’t share the author’s context.
I prefer smaller pull requests whenever possible. They’re easier to understand, review, test, troubleshoot and revert. A reviewer should be able to open a PR and quickly answer three questions:
- What problem are we solving?
- What changed?
- How do we know it works?
If answering those takes a thirty-minute conversation with the author, we should improve how we describe the work. Smaller doesn’t mean splitting code into meaningless pieces. A PR should still be one logical, reviewable change. The point is to minimize the context someone needs to review it correctly, which is rarely the same as minimizing the line count.
Smaller stories make progress visible
The same thinking applies to Jira tickets and user stories. I’ve seen stories that were entire projects. A ticket says “Implement the new business registration workflow.” That sounds reasonable until you realize the workflow includes multiple forms, API changes, database updates, validation rules, permissions, notifications and integrations. One developer now owns understanding and building all of it. The story sits in progress for weeks. Teammates can’t help because nobody knows which parts are done. QA doesn’t know when to start. Leadership has almost no visibility into real progress.
I’d rather break that into smaller, meaningful deliverables: the registration form, the API, server-side validation, document upload, permission checks, the status workflow. Each one gets a clear outcome and its own acceptance criteria. Progress becomes visible, and blockers show up early. If one piece is delayed, we know which piece and why, instead of watching one large ticket sit in progress for three weeks. That’s also most of what sprint carryover is trying to tell you.
There’s a balance. Twenty tickets for something one person can reasonably finish as a single piece of work is noise, and splitting so aggressively that every ticket depends on five others is worse. Break work down enough to make it understandable, testable and deliverable. The ticket count is not the goal.
Clear acceptance criteria save more time than they cost
A ticket can look perfectly clear to the person who wrote it and still be unclear to everyone else. Take “Update the application status when validation fails.” Which validation? What status should be displayed? Does the user get an error message? Is the failure logged? What happens if the validation service is unavailable? What if the user retries?
The developer makes one set of assumptions. QA makes another. The product owner expected something different again. We discover the gaps during testing, the ticket goes back to development, and we spend the next week in meetings, messages and rework, all because nobody spent a few extra minutes clarifying the requirements up front. Some of that rework is work nobody needed in the first place, built carefully to the wrong understanding.
I want acceptance criteria that describe the expected behavior clearly enough that someone unfamiliar with the implementation can follow them. That isn’t a twenty-page specification. It’s answering the important questions before development begins. A few minutes of clarity saves hours of rework.
Say what actually happened
This goes beyond code. It applies to ticket comments, bug reports, incident reports and everyday messages.
Say someone reports that a validation check “wasn’t performed,” when what actually happened is that the validation ran and the result didn’t match. Those are two very different situations. One suggests a missing step. The other says the validation worked and returned a negative result. If both get described as “not checked,” whoever investigates later can easily reach the wrong conclusion, and unless they worked on that code, they have no way to tell the difference.
So I ask teams to be specific. Don’t say something wasn’t checked if it was checked and failed. Don’t say something is broken without describing the behavior you’re seeing. Don’t mark a ticket done without saying what was completed. And don’t assume everyone remembers a decision from a meeting three weeks ago. The person reading your message tomorrow may not have been in the room. Good communication makes sense when the author isn’t around to explain it.
Reviews for understanding, documentation without ceremony
I’ve worked with teams where pull requests get approved almost immediately. Sometimes that’s fine: the change is small, obvious and low risk. Sometimes I wonder whether the reviewer understood it. A code review is a chance to catch problems, share knowledge and improve the codebase, and it only works if reviewing is practical. When a PR holds two thousand lines of unrelated changes, even a good reviewer misses things, because there’s too much to process.
Small, focused PRs make room for the questions that matter. Why this approach? Could it affect another part of the system? Are the failure cases handled? Is there a simpler solution? Is there enough test coverage? Those conversations are worth far more than arguing about formatting, and over time they’re how developers learn from each other.
Documentation works the same way. I don’t mean long technical documents. Sometimes a few sentences in a pull request are enough. Sometimes it’s a short README explaining how to run a service, a comment explaining why a business rule exists, or a note on the Jira ticket recording what the team decided. I’ve watched teams spend hours in Slack reaching a decision and never write it down anywhere. Three months later someone asks the same question and the team has the same conversation again. Not every conversation needs recording. A decision that affects how the system works does, so that someone can find the reasoning later, especially once the person who made it has left. I hold myself to the same rule for architecture decisions.
Across time zones, clarity gets expensive to skip
I’ve spent years working with distributed engineering teams. When the team is spread across time zones, an unclear message costs a lot. Someone asks a question. The person who knows the answer is already offline. The developer waits several hours, or worse, makes an assumption and keeps going, and the next day we find out the assumption was wrong.
Smaller stories, clear acceptance criteria and well-described pull requests cut down how often someone has to stop and ask. A developer should be able to pick up a ticket and understand what needs to happen without scheduling a meeting to get started. A reviewer should be able to understand a PR without waiting for the author to wake up. QA should be able to test a feature without reverse-engineering the requirements. None of that removes communication. It makes the communication you do have count.
What I expect from everyone, regardless of experience
A few things I expect from everyone on an engineering team, whatever their level: say when you’re blocked, ask when something isn’t clear, make an effort to understand the problem before jumping to a solution, take responsibility for your work, and think about the next person who has to read, review, test or maintain what you built.
That last one matters most to me. You might understand your code perfectly today. Will someone else understand it in six months? Will QA know what to test? Will another developer understand why you made a particular decision? Will the next person be able to investigate a problem without calling you? None of these are expectations about memorizing syntax or knowing every framework. They’re expectations about working together.
I don’t believe in dropping accountability because someone has less experience. Everyone has a responsibility to contribute, communicate and improve. I also don’t believe in holding everyone to identical expectations without considering their experience, their responsibilities and the information they were given. A junior engineer may need more guidance. A senior engineer should show more independence and judgment. A tech lead should help others make progress, not only close their own tickets. An engineering manager should notice when the team’s process is creating obstacles. Different roles carry different expectations, and everyone deserves to know what those expectations are.
If someone has the information, tools and support they need and still consistently struggles to deliver, that needs addressing. If the whole team keeps asking the same questions or misreading the same requirements, the problem is probably how we communicate and organize the work, and we should fix that instead. Being understanding doesn’t lower the standard. It makes sure the standard is reasonable, clear and applied the same way to everyone.
I don’t want to be the person who knows everything
Early in my leadership career I felt responsible for having an answer to every question. Developers came to me when they were stuck. Product asked me about implementation details. QA asked me to clarify expected behavior. I tried to help everyone, and eventually I became the bottleneck. When every decision runs through one person, the team can’t move without that person.
My job isn’t to remember everything or make every technical decision. It’s to create an environment where people can make good decisions without depending on me: encouraging knowledge sharing, making requirements clearer, helping developers break down work, leaving room for questions, and making sure important decisions don’t live only in someone’s head. A team shouldn’t stall because one developer takes a vacation, and a project shouldn’t stop because the person who built a feature has moved on. If everything depends on one person knowing everything, that’s a risk, whatever it looks like from the outside. It’s also why I mentor engineers until they can replace me.
Asking for clear tickets, smaller PRs and better documentation isn’t micromanagement. I don’t need to tell an experienced developer how to implement every feature. I want them to understand the problem, the constraints and the expected outcome, and then use their experience to pick a solution. In reviews, I don’t want developers defending every line. I want the team to understand the reasoning behind the decisions that matter. Clear expectations give people more independence, because they spend their time solving problems rather than guessing what someone meant.
Experience is also about how much easier you make things for the people around you. A senior engineer who can solve a hard problem is valuable. One who can explain it, help others understand it, and keep the team from hitting it again is more valuable. The same goes for engineering leaders. That takes patience, and it sometimes means explaining something that seems obvious to you and isn’t obvious to someone else. I’ve had to remind myself of that for my whole career. The reverse is true too: there’s plenty other engineers know that I don’t. That’s why it’s a team.
What I try to encourage on my teams
- Keep pull requests focused. One logical change is easier to review than five unrelated ones bundled together.
- Break large stories into smaller deliverables, so progress is visible and problems surface early.
- Write acceptance criteria someone else can understand. Don’t assume the developer, QA and the product owner read a ticket the same way.
- Explain why, not only what. Code says what the system does. Context says why.
- Make important decisions discoverable, instead of leaving them in Slack threads or someone’s memory.
- Encourage questions. I’d rather someone ask than spend two days building the wrong thing.
- Review for understanding. A review should improve quality and share knowledge, not just satisfy a process.
- Don’t let the team depend on one person. Share knowledge so work keeps moving when someone is away.
None of this is complicated. Doing it consistently is what makes the difference.
Short answers
Should a senior engineer know everything about the codebase?
No. A senior engineer should be more independent at breaking down problems, spotting risks and investigating unfamiliar code, but nobody can know a business rule that was never explained or a decision that was never documented. Experience changes expectations; it doesn’t replace clear requirements.
Why are smaller pull requests better?
They’re easier to understand, review, test, troubleshoot and revert. A reviewer should be able to tell what problem the PR solves, what changed and how we know it works without a long conversation. Smaller means one logical change with less context required, not fewer lines for their own sake.
How small should a user story be?
Small enough that it has one clear outcome and its own acceptance criteria, so progress is visible and blockers show early. Not so small that every ticket depends on five others. A story like “implement the registration workflow” is usually several deliverables: the form, the API, validation, uploads, permissions and status changes.
What should acceptance criteria include?
Enough expected behavior that someone unfamiliar with the implementation can follow it: which cases apply, what the user sees, what gets logged, and what happens on failure or retry. Answering those questions before development starts prevents the developer, QA and the product owner from each assuming something different.
Make the work easier for the next person
Software engineering is already complicated: frameworks, languages, databases, services and business rules, with requirements changing and people joining and leaving. Nobody can remember all of it, and we shouldn’t expect them to. What we can do is write a clearer ticket, submit a smaller pull request, explain a decision, document an assumption, and ask a question before spending two days going the wrong way.
A productive engineering team isn’t the one with the smartest developer or the deepest knowledge of the codebase. It’s the one where people can understand the work, help each other, and make progress without waiting on someone else.
As an engineer, I don’t expect myself to remember everything. As a leader, I shouldn’t expect it of anyone else. I do expect us to communicate clearly, take ownership, keep learning, and make things easier for whoever comes next. The goal isn’t a team where everyone knows everything. It’s a team where everyone can succeed without having to.