"How do I get promoted?" as a software developer can be a tricky question, and the answer is often highly dependent on where you work. Each organization has its own processes, and especially at higher levels, budget and politics can often (unfortunately) come into play. But if we consider the more general question, "How do I advance my career?", I think we can still say something useful, both for developers looking to grow and for managers looking to help guide them.
If you wanted to get promoted at pretty much any company (and thus get paid more money), you need to provide -- and demonstrate that you are providing -- more value1. Thus, regardless of your organization's titles, job descriptions, or leveling guide, the shared concept behind all of them is an increasing level of impact. Each successive level builds upon the last, with increasing expectations that delivery will be faster, of better quality, solving more complex and more critical problems.
I think of the software engineering career path as consisting of two distinct phases. The first phase is relatively straightforward, as a novice developer grows from a beginner into a seasoned professional. At the outset, an entry-level developer will generally need a high degree of supervision to be productive, and their delivery will be slower, have more defects, and tackle less-complex problems than their peers. Given this, their impact on an organization is low, and can even be net-negative when we consider the amount of time taken by more senior folks required to supervise the junior developer. In contrast, a fully-trained senior developer will require much lower amounts of supervision to deliver more complex solutions of higher quality. Their impact is much higher because they can deliver more complex tasks faster and with fewer defects; you might consider such senior developers the workhorses of any software development organization.
The through-line of this first phase is that the developer, as they increase their output and decrease the amount of supervision required, is increasing their impact to the organization entirely through individual contributions. While growth in this area might increase at different rates during their career, it does eventually plateau. There are only so many hours in a day, and one can only type so fast. To grow further professionally, a software developer must launch a second phase of their career and start to provide value along a different axis.
This second phase of a developer's career is much more open-ended. They are already a skilled professional, but to further increase their value to an organization, they cannot rely just on individual contributions; rather, they also must positively impact the productivity of those around them. If the first phase of a developer's career is about expanding the depth of their knowledge and skill in the software engineering domain, the second phase is predominantly about expanding the breadth of their impact. There are many ways to do this, and they can lead to different, divergent career paths.
The obvious way for most professionals to make a larger impact on any organization is to go into management, and that's certainly true for software developers. However, developers are famed for their tendency towards being uninterested and/or unsuited to management; even many who could do it well don't find the work especially fulfilling, and ultimately transition back to full-time development. Given the need for most ambitious employees to continue advancing, it behooves any software organization to have well-defined (and well-compensated) career paths for senior developers that don't involve going into management.
The answer many organizations have come up with is to define a career path for Software Architects, where developers can stay technical, but deliver a wider impact not just by writing software, but through the design of larger, area- and organization-wide systems that are ultimately built by teams and groups of teams. It is a way of providing leadership in software development without taking on management responsibilities. While this is an attractive option for some, senior architects do tend to drift away from the code, spending less time on implementation and more on design, communication, and documentation, which can be less satisfying for others. It can also be difficult to get started along this path, as the kinds of meaty projects that can demonstrate skill as a software architect don't come along all the time, and when they do, they are often handed directly to experienced architects that already have a reputation for delivering on such large initiatives.
There are, however, other ways for ambitious senior developers to increase the scope of their impact. Besides system architecture, I often suggest looking at things like building tools, improving processes, enhancing testability, or even leveling up documentation. Whatever area they wish to specialize in, the developer who wishes to progress beyond a senior level needs to start solving not just the problems in front of them, but instead anticipating and solving entire classes of problems, improving not just their own productivity but that of others they work with.
One of the challenges for developers in this second phase is that their progression must be, at least in part, self-directed. Managers usually cannot just hand high-impact tasks to a senior developer looking to do more, in part because managers don't always know themselves what those tasks should be. Part of the value provided by more-than-senior developers comes from their initiative in identifying and defining potentially high-impact tasks. What managers can do is provide feedback on the tasks identified, using context from the business and the rest of the organization to help evaluate which tasks are truly worth investing in at the current moment.
The self-directed nature of this phase of career progression presents other difficulties as well. How is a developer supposed to identify, define, and then ship impactful projects when they're busy completing all of the regular tasks that are the core part of the job? The ideal case is when you can argue to have your career-advancing project prioritized as part of the official roadmap, but failing that, I usually advise trying to ship improvements in the context of your regular work. For instance, instead of just solving the problem at hand, build part of the solution as a tool or library that not only solves the current problem, but that can also be reused by other teams to solve future problems.
However, one danger with just trying to deliver broad impacts as part of your regular work is that you might succumb to the "unsung hero" pitfall, where key stakeholders aren't aware of the impact you're having, or don't know that you're the one creating it. Here, communication with your manager is key: if they're aware of what you're doing and what you've accomplished, they can spread the gospel of how great you are and help push your career forward. An even bigger conundrum can befall developers who become too associated with their current assignment: they can find themselves pigeonholed into that specific area, becoming so entwined with a particular system and its operation that others cannot imagine that developer doing anything else. Someone thus pigeonholed must first work to make themselves less essential to that system before they might be allowed to progress on to bigger things.
Given the initiative required to navigate this second phase of their career, it shouldn't be a surprise that some senior developers never even attempt it. They find themselves perfectly content (and well-compensated) as professional developers, and desire nothing more than to deliver high-quality software and let someone else handle details outside their purview. This is fine! Not everyone in an organization needs to be a leader, and so as long as an organization has sufficient leadership, development teams can be filled out quite capably with workhorse senior devs.
One caveat to the previous point is that developers should be mindful not to plateau too early. A developer who is content to remain a mid-level or even a junior developer is a lot less valuable to an organization, and they will eventually find themselves put on less interesting and less rewarding projects. Quality engineer organizations will avoid hiring them, figuring that someone who is not progressing in their career is not worth investing in. In all honesty, a developer in this category -- one who is not driven to be at least really good at the thing they do all day -- should seriously consider whether perhaps they would enjoy a different career instead.
I think one of my favorite parts of being a developer is the freedom I have to improve my own working conditions. If a tool I use is slow or clunky, if a process requires too many manual steps, if the data I need is just too hard to find, I have the ability to fix all of that! It takes time and skill and effort, and often isn't glamourous work, but it can be very valuable. Reflecting on my own career, I think a big reason I was able to advance is that, when I saw value in improving something, I never considered fixing it to be beneath me, or not my problem, or otherwise outside my purview. I didn't always succeed, and sometimes I spent time on things that turned out to be not that important, but I consistently proceeded with the idea that "if it makes my job easier, it will probably make other people's jobs easier as well." That turned out to be true often enough that I was eventually able to make a large impact on my team and my organization, and from there, professional advancement followed.
More than a dozen paragraphs later, I don't think there's a simple answer to how to get promoted in software -- there's too much that's idiosyncratic about each individual, and each company they work for, for a simple set of steps to ever be widely applicable. Still, I think the idea of focusing on making a larger impact, on providing greater value, is a useful heuristic that anyone can apply against their own professional efforts to determine a fruitful path forward.
1. Here I'm ignoring shortcuts to promotion, such as engendering favoritism. I'm sure there are some organizations that tolerate, and even encourage, such shenanigans, but I'm not interested in being a part of one of them.