Maximizing Business Impact with My Coding Expertise
Written on
Chapter 1: Overview of My Year as Tech Lead
This article outlines the significant development tasks I accomplished in the past year as a tech lead, focusing on their positive impact on our business performance.
The primary goals I prioritized included:
- Addressing challenges that hindered our team from deploying code efficiently.
- Monitoring deployment frequency and lead times as key performance indicators.
- Establishing measurable objectives and automating data collection whenever feasible.
- Enhancing error reporting and log data; analyzing time required to resolve production issues and identifying bottlenecks, particularly those stemming from poor error messages or stack traces.
- Exploring new technologies and reviewing our software architecture to identify alternative solutions to ongoing issues, along with creating "blueprints" of best practices for team reuse.
When I took on the role of tech lead for a small development team over a year ago, I anticipated both challenges and rewards. Though I had previously led front-end teams, this was my first experience managing service and database development. I knew it would push me beyond my comfort zone and require substantial learning.
Unexpectedly, I found myself coding less than anticipated, and I sometimes felt guilty watching my colleagues write more code and implement features at a faster pace. I consistently questioned my manager during our monthly one-on-ones about whether my performance met expectations and if I should be coding more. Each time, my manager reassured me that my contributions were valuable and that we were achieving our business objectives more effectively with my leadership.
Section 1.1: Eliminating Deployment Hurdles
In my initial one-on-ones, team members frequently cited that feature specifications often changed after deployment to the testing environment. A single developer would spend weeks on a feature branch, and merging it into the development branch was a lengthy process. Following a manual deployment to the testing environment, the QA engineer would spend days testing, leading to feedback that took time to implement. Typically, multiple large features were under development simultaneously, resulting in the team often releasing unfinished builds just to ship features that had been in progress for months. The sunk-cost fallacy made reverting production releases challenging, and bugs that slipped through were addressed in a frantic rush until resolved.
Section 1.2: Enhancing Planning Processes
To rectify the issue of feedback and specification changes occurring post-development, we needed to revamp our planning approach. Initially, the process involved:
- The Product Owner (PO) outlining a customer problem and a corresponding feature.
- The design team producing UX iterations until final designs were agreed upon.
- The development team receiving the design and specifications bundled into a single task for implementation.
To close the gap between the initial definitions and the final implementations, we implemented two critical changes:
- A pre-design meeting was added, including a development team member, a design team member, the PO, and the Project Manager (PM). This meeting facilitated the identification of technical issues early on and ensured a shared understanding of business logic.
- The design team and PM began structuring work into smaller, manageable tasks rather than a single large feature. This approach enabled quicker development and testing cycles, fostering timely feedback and reducing bugs.
These adjustments may seem straightforward in hindsight, but they required persistent and respectful advocacy during our monthly retrospectives. It took over six months for the team to adapt fully to this new workflow.
Section 1.3: Streamlining the Development Process
To enable quicker iterations, we focused on improving our deployment process by incorporating milestones, versioning, and an automated build and deployment pipeline using GitLab CI/CD.
My role was to persuade the developers of the benefits of having milestones and versioned releases. I emphasized that a single-click revert option would minimize panic and reduce human error. Additionally, I secured the necessary DevOps resources to establish the GitLab CI/CD pipeline. After outlining the DevOps tasks and preparing the build scripts, we coordinated the implementation together.
- Quick side note: Why is it that everyone in IT is labeled a developer or engineer, except for the DevOps team member?
This effort took about a month of discussions and documentation, but the payoff was significant; we could now deploy and revert builds in different environments at the click of a button. As a result, our deployment frequency increased to at least once a week, with defect rates decreasing from 60% to 40%, and recovery times shortening to one to two hours instead of days.
Section 1.4: Measuring Software Performance
Upon joining the team, a significant area of concern was the web app's performance. Users reported slow page loads and sluggish actions, negatively impacting customer satisfaction. Fast forward six months, and we achieved considerable improvements in load times and responsiveness without directly optimizing database queries or consolidating GraphQL API endpoints.
Instead, I focused on establishing reliable performance metrics. By implementing Sentry for page performance data collection and conducting stress tests on our REST API endpoints, I identified bottlenecks and presented this data to the PO and the team. By prioritizing high-traffic pages, we reserved time on our roadmap for performance enhancements.
After analyzing the collected data, we identified numerous manageable issues that could enhance performance. My teammates were able to tackle these challenges independently, allowing us to improve application performance without hindering new feature development.
Section 1.5: Revamping Error Reporting and Logging
Previously, our team struggled to manage a high volume of reported issues, leading to frustration among users and developers alike. We relied on Sentry.io to track errors, but the sheer volume made it difficult to pinpoint specific customer-reported events.
To improve manageability, we first needed to shift the team's culture. We made two commitments:
- Every reported issue would receive feedback and be tracked on our Kanban board.
- Expected exceptions and warnings would fail silently to prevent log clutter.
Importantly, we also pledged to investigate unforeseen behaviors and edge cases. As the team recognized the need to manage both internal and customer reports effectively, we began to see steady progress.
My role was to advocate for the importance of addressing customer complaints and ensuring that the development team prioritized cleaning up error logs. Rather than the team undervaluing software quality, the lack of clear standards for quality measurement was the root issue I aimed to address.
Ultimately, it was my persistence in debugging and consistently reporting on unresolved issues that fostered a culture of accountability. As the PM highlighted edge cases from our orders, I insisted that we should not introduce new features until existing complaints were addressed.
Section 1.6: Research and Proof of Concept
A significant part of my role involved researching solutions and providing proof of concepts. This year, we transitioned from a single-page create-react-app to Next.js with server-side rendering and implemented data caching with Redis and IndexedDB.
While the team had previously decided on these changes, my responsibility was to facilitate the transition without disrupting ongoing development. I created a subpage with server-side rendering that interacted with our database while requiring user authentication.
Once I established the "blueprint," we could efficiently schedule tasks for refactoring other pages and implementing the necessary changes for Redis and IndexedDB.
The key takeaway here is that anyone on the team could have undertaken this research. My network, experience, and curiosity facilitated progress, but the critical factor was my willingness to take ownership of the challenge for the team's benefit.
In summary, when prioritizing tasks, I reflect on which actions will empower my teammates. Although I still engage in coding, I focus less on coding tasks unless they are time-sensitive. Much of my time is dedicated to meetings, analyzing dashboards, learning about our domain (grocery delivery software), setting metrics, researching, collaborating with colleagues, and studying relevant materials. These activities ultimately enhance my team’s efficiency and contribute to the long-term stability of our software.
Thank you for your time—your engagement is appreciated! If you found this content helpful, please share your thoughts in the comments, and consider following for more insights. If you have suggestions for improvement, I’d love to hear them.
The first video, "7 Ways to Create a Small Business as a Programmer," offers insights into lucrative side hustle ideas tailored for developers looking to make an impact in the business realm.
The second video, "The Truth About Learning to Code to Start a Business," dives into the realities of coding education and its significance in entrepreneurial ventures.