When people ask me the difference in roles of an Engineer I, an Engineer II, and a Senior Engineer, I use a “Dot” analogy. Imagine there is a map of dots that you need to draw. An Engineer I is given starting dot, destination dot, and a path to connect each dots. The responsibility of the engineer is to deliver results given the map. On the other hand, an Engineer II is only given the starting dot and the destination dot. The engineer will need to define the path between the two dots and deliver results. What about a Senior Engineer? He/She is given only the destination dot. He/She will need to find the right dot to start, build the entire map and deliver. Depending on the seniority, the size of the map will change, and there could be cases where the destination dot needs to be defined.
Using the analogy, coding is the easiest task. If you are given all the instructions to implement, you just need to follow instructions to write a few if/else statements and for loops. Only times you need to come up with the right algorithms and data structures like dynamic programming and tries are when you are the interviewer or the interviewee or when you are solving some Leetcode questions to prep for upcoming interviews. Coding is the bare minimum expectation as a software engineer so there isn’t much complexity here.
What is more difficult then? I would have said technical designs 3 years ago. Designs are usually the ones that hit a lot of obstacles and evaluating pros and cons can be difficult. In addition, coming up with optimal solutions is usually one of the critical checkboxes for a promotion to get to a senior engineer. Yet, in many cases, designs are simply finding the paths you want to take when connecting the two dots. For example, adding a new feature or defining a new API to a service that you own are a typical Eng II projects. While there could be multiple acceptable solutions, it is a matter of time and investigation that will get you to the result you want.
Destination dots are usually defined by product or leadership (i.e. improve latency of a landing page by xxx ms, decrease the technical expense by xxx%, etc). Senior engineers will need to deal with the ambiguity and find the dot to start. In many cases, these come with experience and they will become natural with time. In my opinion; however, that is only because with time, you start to realize the true responsibility of different services and organizations.
When I was at Amazon, I was given an org-level goal to reduce the number of AWS hosts to run the service my team owned. The service was getting several hundred thousand requests per second and I focused on identifying the ways to reduce the number of requests we got. In the end, I was able to identify series of business logic, which our upstreams should have done, and migrated the logic over to the right upstreams, removing more than 50% of the requests per second.
Once ownership is identified, it’s a matter of breaking the big problem into the right buckets. Starting dots are usually identifiable once you have a clear understanding of the responsibility of different systems and orgs. There will be more complications when the ownership isn’t too clear and you have to define it along the way, but at the end, this is truly interesting problem to solve and you will get more visibility as you do so.