Category: Featured

Driving innovation: How vFunction accelerates Turo’s journey to 10X scale

turo gartner summit session

Adam Safran, Senior Engineering Manager at Turo, took the stage with me at the 2024 Gartner Application Innovation & Business Solutions Summit to discuss how vFunction’s architectural observability platform supports Turo’s journey to 10x scale.

 

Turo, the world’s largest car-sharing marketplace, is on a mission to put the world’s 1.5 billion cars to better use. Since 2010, Turo has consistently grown to amass over 3.5 million active guests and over 6.5 billion miles driven. This growth is great, but it also introduces challenges.

Turo’s growth pushed the limits of its monolith

Turo’s growth presented new challenges for its twelve-year-old monolithic application and rapidly expanding engineering team. 

To address these concerns, Turo CTO Avinash Gangadharan proposed a mandate to achieve 10x scale. He developed two new engineering domains: a platform domain focused on developer experience and reliability and a core services domain focused on scale.

turo team structure

Adam’s API services team acts as a bridge between the two domains. However, the proposal faced several challenges:

  1. Justifying the initiative to leadership: When things are going well, it can be challenging to explain to leadership the necessity of investing in scale. Turo’s consistent growth required investing in scalability without sacrificing new feature development.

“The challenge is that there’s sort of a sense of if ‘it ain’t broke, don’t fix it.’”

Adam Safran, Senior Engineering Manager at Turo
  1. System and organizational scale challenges: Turo’s monolithic application faced several issues due to growth:
    • The number of developers contributing to Turo’s codebase more than doubled from 28 contributors in 2017 to 72 in 2024
    • Turo’s engineering team grew from 80 engineers in 2020 to over 200 in 2024
    • The number of tables grew from 62 in 2011 to 491 in 2023 
    • Their reservation table went from 13 in 2011 to 36 in 2019

      Turo began experiencing deployment issues, with releases taking 5-10 hours to get code into production. Organizational silos emerged, leading to increased ambiguity around domain ownership.
  2. Loss of modularity: As new domains were added to the application, classes written for a single purpose took on other responsibilities, leading to entanglement. Database tables previously called from one logical domain were called from two different places, mixing up their data layer with their business logic. As a result of over a decade of ad hoc development, Turo’s architecture lost its modularity, impacting the application’s scalability and resiliency.
turo monolith
Turo’s monolithic application as shown in vFunction. “This is what happens over twelve years of ad hoc development to build a world-class vehicle marketplace without pausing to consider scale,” said Adam Safran.

The shift from monolith to microservices

To address the challenges posed by their monolithic application, Turo chose first to extract its conversation service. The decision was based on the service’s frequency of use and overall latency issues. The goal was to improve engineering velocity by reducing complexity through distinct microservices that can scale separately and provide clarity on domain ownership. 

Once the conversation service was modernized to a “lean, mean microservices machine,” Turo achieved the following results: 

  • Faster average response times that went from half a second to 19 milliseconds with the 99th percentile response times improving from about seven seconds to just under one second
  • 25-100x better sync times
  • Improved code deployment from 5-10 hours to just five minutes
25X improvement

Challenges following microservice extraction

However, soon after creating the microservice, Turo realized that the application’s architecture could quickly become entangled without complete visibility, with teams adding new code and dependencies to new microservices. These changes might not be discovered until weeks or months later, leading to Adam’s API services team having to untangle “spaghetti code.”

spaghetti code

vFunction — visualizing architecture, paving the way to scalability

To ensure vigilance in observing the application’s software architecture, Turo turned to vFunction to provide continuous architectural observability with dynamic and static code analysis and a real-time view of the application’s dependencies. vFunction helps the microservices architecture remain resilient and scalable while monitoring for technical debt accumulation and reducing software complexity as the team adds new features.

“We’re making this investment now in scale while the wheels are moving so that our product teams can continue to focus on the features that our users want.”

Adam Safran, Senior Engineering Manager at Turo

With vFunction, Turo identified a repeatable process to extract microservices and achieve scalability goals. Here’s what Adam describes as the best practices when modernizing an application:

  • Use vFunction to understand your domain, the interconnections between services, and how to maintain service boundaries to avoid technical debt
  • Over communicate with your teams about what the organization is doing and how they are doing it
  • Break down organizational silos to reduce domain pollution
  • Share your journey to help uplevel the organization
  • Document successes to demonstrate ROI
  • Rinse and repeat

As Turo’s business continues its growth trajectory, vFunction architectural observability enables the team to visualize its application and continuously find and fix technical debt before it has a chance to take root.

Organizations that deploy architectural observability experience improved application resiliency and scalability while increasing their engineering velocity. This ensures continued innovation and sharpens their competitive edge.

“I wish we had vFunction when I started at Turo. This kind of architectural observability gives us a much better understanding into our application and helps us with decision making as we move forward.”

Adam Safran, Senior Engineering Manager at Turo

If you’d like to learn more about how vFunction can help your organization, contact us. Tell us the big goals for your application and we’ll show you how architectural observability gives you a clear path to get there faster.

How to Measure Technical Debt: Step by Step Guide

how to measure tech debt

To meet the challenges posed by customers and competitors in today’s rapidly changing marketplace, you must regularly update and modernize the software applications on which your business operations depend. In such an environment, technical debt is inevitable and highly detrimental. Knowing how to measure and manage technical debt effectively is essential.

Understanding how much technical debt a company has is crucial for setting up accurate metrics and realizing the extent of the debt. Getting a complete picture of the technical debt metrics within your organization’s applications makes it easier to manage and track.

According to Gartner, companies that manage technical debt “will achieve at least 50% faster service delivery times to the business.” On the other hand, organizations that fail to manage their technical debt properly can expect higher operating expenses, reduced performance, and a longer time to market. As a report from McKinsey makes clear, “Poor management of tech debt hamstrings companies’ ability to compete.” With so much riding on managing and remedying technical debt, it’s a topic that architects, developers, and technical leaders must know well.

What is technical debt?

The term “technical debt” was coined in 1992 by computer scientist Ward Cunningham to vividly illustrate the long-term consequences of the short-term compromises and workarounds developers often incorporate into their code. Much like financial debt, where borrowing money now leads to interest payments later, technical debt accumulates “interest” through increased development time, decreased system stability, and the potential for future bugs or failures.As TechTarget explains, technical debt is an inevitable consequence of the “build now, fix later” mentality that sometimes pervades software development projects. With tight deadlines, limited resources, or evolving requirements, developers may opt for quick-and-dirty solutions rather than investing the time and effort to build robust, scalable, and maintainable code.

risk of not managing tech debt

In essence, technical debt is the result of prioritizing speed over quality. While these shortcuts may seem beneficial in the short term, allowing teams to meet deadlines or deliver features faster, they can significantly impact reliability down the line. Just as ignoring financial debt can lead to financial ruin, neglecting technical debt can crush a software project, making it increasingly difficult and expensive to maintain, modify, or extend.

The snowball effect

Technical debt doesn’t just remain static; it accumulates over time. As teams implement more quick fixes and workarounds, the codebase becomes increasingly convoluted, complex, and difficult to understand. This, in turn, makes it harder for developers to identify and fix bugs, add new features, or refactor the code to improve its quality. The result is a vicious cycle where technical debt begets more technical debt, leading to a gradual decline in the software’s overall health and performance. Growing technical debt signifies that the complexity of the code is increasing, which will eventually require untangling and negatively impact code quality.

Understanding the nature of technical debt and its potential consequences is the first step toward managing it effectively. Although the impacts of technical debt can be gradual, they can result in massive disadvantages in the long run.

Disadvantages of technical debt

Since no software development project ever has all the time or resources required to produce a perfect codebase, some technical debt is unavoidable. That’s not necessarily bad if an application’s technical debt is promptly “paid off.” Otherwise, just as with financial debt, the costs of repaying the “principal” plus the “interest” on the debt can eventually reach crippling proportions.

The “principal” portion of technical debt is the cost of fixing the original code, dependencies, and frameworks to enable it to function in today’s technology environment. The “interest” is the added cost of maintaining such applications, which continues to compound over time. The challenge is keeping an aging and inflexible legacy application running as it becomes increasingly incompatible with the rapidly changing modern infrastructure it operates on top of.

Technical debt can significantly hinder a company’s ability to innovate. According to a recent U.S. study, more than half of respondents dedicate at least a quarter of their annual budget to technical debt. Poorly written code is a common form of technical debt, often leading to increased maintenance costs and reduced code quality.

And other costs of technical debt are, perhaps, even worse than the financial ones:

  1. Less innovation: The time developers devote to dealing with technical debt is time taken away from developing the innovations that can propel the business forward in its marketplace.
  2. Slow test and release cycles: Technical debt makes legacy apps brittle (easy to break), opaque (hard to understand), and challenging to upgrade safely. That means teams must devote more time to understanding the potential impact of changes and testing them to ensure they don’t cause unexpected disruptions in the app’s operation.
  3. Inability to meet business goals: This is the inevitable result of the previous two issues. In today’s environment of rapid evolution in technology and market requirements, the inability to quickly release and deploy innovative new applications can impede a company’s ability to meet its goals.
  4. Security exposures: Because modern security concerns were typically unknown or disregarded when older apps were designed or patched, security-related technical debt often constitutes a significant vulnerability for legacy code.
  5. Poor developer morale: For many developers, dealing with technical debt can be mind-numbing and frustrating. In one survey, 76% of respondents affirmed that “paying down technical debt” negatively impacted their morale.

Ward Cunningham explains the destructive potential of technical debt this way:

“The danger occurs when the debt is not repaid. Every minute spent on not-quite-right code counts as interest on that debt. Entire engineering organizations can be brought to a stand-still under the debt load of an unconsolidated implementation.”

While increasing amounts of technical debt feels normal to most, it’s essential to understand the impact so that managing it becomes a priority. Teams must also be aware of various types of tech debt.

What are the types of technical debt?

Technical debt manifests in various forms, each with unique characteristics and potential consequences. Understanding these types is crucial for effectively identifying and managing technical debt within the applications that an organization owns and maintains. Here are examples of tech debt that can arise.

  1. Code debt: This is the most common and easily recognizable type of technical debt. It refers to accumulating poorly written, overly complex, or outdated code. Code debt can result from rushed development, lack of adherence to coding standards, or simply the evolution of technology and best practices over time. Symptoms of code debt include excessive bugs, difficulty understanding and modifying the code, and slow performance. Additionally, changing existing code can be particularly challenging, often requiring significant time and effort to ensure stability and maintainability.
  2. Design debt: Design debt arises when the software’s design is suboptimal, leading to challenges in implementing new features or modifying existing functionality. This can occur due to a lack of upfront design, changes in requirements, or a failure to adapt the design as the software evolves. Design debt can manifest as tightly coupled components, hard coded dependencies, or a lack of modularity.
  3. Testing Debt: Insufficient or inadequate testing can lead to testing debt. This can include a lack of automated tests, outdated tests that no longer reflect the current state of the software, or simply a culture of neglecting testing in favor of rapid development. Testing debt increases the risk of bugs and regressions, making it harder to ensure the software’s reliability.
  4. Documentation Debt: Outdated, incomplete, or inaccurate documentation constitutes documentation debt. This can make it difficult for new developers to understand the codebase, for existing developers to remember how things work, or for stakeholders to understand the software’s capabilities and limitations. Documentation debt can lead to misunderstandings, errors, and delays in development.

Architectural technical debt

At vFunction, we also focus on an additional aspect of technical debt that can accumulate: architectural technical debt. While sharing similarities with the types mentioned above, architectural technical debt is more deeply ingrained in the software’s structure. It refers to compromises made in the overall architecture or design of the system for short-term gains, such as meeting a tight deadline or delivering a specific feature. These compromises may involve:

  • Architectural drift: Deviation from the intended architecture over time due to ad-hoc changes or lack of governance.
  • Intentional violations: Deliberately violating best practices or established architectural principles due to time constraints or other pressures.
  • Unstable shortcuts: Using temporary or unreliable solutions that provide a quick fix but may not be sustainable in the long run.

While incurring architectural technical debt can sometimes be a strategic decision, it’s essential to know the associated costs and drawbacks, as well as keeping a metric in place to measure and monitor changes. Over time, architectural debt can lead to increased complexity, reduced flexibility, and even system instability.

Understanding the different types of technical debt and their potential impact is a critical step in managing this hidden cost of software development. In the next section, we’ll explore how to measure technical debt so you can understand its extent and make informed decisions about how to address it.

How to measure technical debt

As we’ve seen, companies need to understand how to manage technical debt. Yet, according to an article in Forbes, technical debt is difficult to measure. The article quotes Sven Blumberg and Björn Münstermann of McKinsey, saying, “Technical debt is like dark matter: you know it exists, you can infer its impact, but you can’t see or measure it.” Blumberg and Münstermann list some informal indicators of technical debt, such as product delays, out-of-control costs, and low developer morale. But are there any formal methods available to quantify the amount of technical debt that characterizes a particular application or an entire application portfolio?

Some have proposed using metrics such as cyclomatic complexity (the number of possible execution paths in the code) and cognitive complexity (a measure of a human’s difficulty in understanding the code and all its possible execution paths). Code quality metrics can also be used to calculate the remediation cost, which helps determine the technical debt ratio (TDR). TDR measures the overall future cost of technical debt in terms of time or resources, providing a clearer understanding of the effort needed for quality improvement. The problem with such indicators is the difficulty of measuring them in a large monolithic codebase with millions of lines of code.

survey most damaging types of tech debt ranked
Architecture technical debt consistently appears as the most damaging and far reaching type of technical debt in surveys, analyst reports, and academic studies.

Why knowing how to measure technical debt is crucial

Many companies today depend on traditional monolithic applications for business-critical processing. Due to their age and development over time, such apps typically have substantial technical debt that limits their ability to integrate and take advantage of today’s cloud-based technological ecosystem.

The solution is modernizing those legacy apps to give them essentially cloud-native capabilities. And that means dealing with the technical debt that’s holding them back. But, as management guru Peter Drucker famously said, “You can’t improve what you don’t measure.” Measuring the technical debt of legacy apps is critical to bringing them into the modern technological age. Tracking technical debt over time is crucial for continuous improvement and ensuring long-term code quality. One recent application modernization white paper explains it this way: “For any application modernization strategy to be successful, organizations need to first understand the complexity, risk, and technical debt of their current application estate. From there, they can prioritize and make the appropriate substantial investments into technology, resources, and the time it takes to implement the strategy.”

However, technical debt is notoriously difficult to identify and measure. Luckily, there are tools that can help to detect and monitor technical debt so that teams can stay on top of it. Next, let’s look at a few of the most popular tools for identifying technical debt and helping teams stay on top of it.

“Poor management of tech debt hamstrings companies’ ability to compete.”

McKinsey & Company

Five best tools for measuring technical debt

The first step to tackling technical debt is understanding its extent and nature within your codebase, infrastructure, and overall architecture. Various tools can automate this process, providing valuable insights and metrics to guide your debt management strategy. Additionally, emphasizing the importance of code ownership can significantly aid in managing technical debt by ensuring clear ownership and contributions from fewer developers, thus minimizing unreliable code and tech debt.

According to Gartner, technical debt analysis tools can fall into a few categories. Below is a diagram that explains the types of tools, their capabilities, and where they reside within the SDLC.

managing tech debt enterprise

Based on these categories, here are five of the best tools available for measuring different types of technical debt:

vFunction

This AI-powered platform tackles architectural technical debt in large, complex legacy systems and modern, cloud-based microservices. vFunction statically and dynamically analyzes applications, identifying hidden dependencies, outdated architectures, and potential risks. It then provides actionable insights and recommendations for refactoring, modernizing, and systematically reducing technical debt.

CAST Software (Cast Imaging)

Cast Imaging takes a comprehensive approach to technical debt assessment, analyzing code quality, architecture, and security vulnerabilities. It provides a detailed view of the technical debt landscape, including metrics for code complexity, design violations, and potential risks. This holistic approach helps teams prioritize their remediation efforts based on the most critical areas of debt.

SonarQube

This popular open-source platform is a versatile code quality and security analysis tool. While not explicitly focused on technical debt, SonarQube provides valuable insights into code smells, bugs, vulnerabilities, and code duplication, often indicative of technical debt. By regularly using SonarQube, teams can proactively identify and address code-level issues contributing to technical debt.

Snyk (Snyk Code)

While primarily known for its security focus, Snyk Code also offers features for analyzing code quality and maintainability. It can identify issues like code complexity, potential bugs, and security vulnerabilities, often intertwined with technical debt. By addressing these issues, teams can improve code quality and reduce the overall technical debt burden.

CodeScene

This unique tool goes beyond static code analysis by analyzing the evolution of your codebase over time. It identifies hotspots—areas of the code that are frequently changed and prone to accumulating technical debt. It also analyzes social aspects of code development, such as team dynamics and knowledge distribution, to identify potential bottlenecks and risks. This behavioral code analysis provides valuable insights into the root causes of technical debt, helping teams address it more effectively.

By leveraging these tools, you can comprehensively understand your technical debt landscape. This knowledge empowers you to make informed decisions about which areas of debt to prioritize and how to allocate resources for remediation. Many of these tools can be embedded directly into your development pipelines with automated scans and monitoring to keep your teams informed as a project evolves. As we have discussed, monitoring and managing technical debt is crucial; these tools can help keep that at the forefront of our minds. Let’s review some tips on monitoring and managing technical debt.

Monitoring and managing technical debt

A significant portion of technical debt in legacy applications stems from their monolithic architecture and reliance on outdated technologies. These applications often have a complex codebase with hidden dependencies, making it challenging to assess and address technical debt effectively.

In 2012, a team of researchers proposed a groundbreaking approach for measuring architectural technical debt based on dependencies between architectural elements in the code. The paper “In Search of a Metric for Managing Architectural Technical Debt,“ recognized as the “Most Influential Paper” at the 19th IEEE International Conference on Software Architecture (ICSA 2022), has paved the way for using machine learning to quantify technical debt.

This modern approach leverages machine learning (ML) to analyze the dependency graph between classes within an application. The dependency graph, a directed graph representing dependencies between entities in a system, provides valuable insights into the complexity and risk associated with the application’s architecture.

By applying ML algorithms, we can extract three key metrics that represent the level of technical debt in the application:

  1. Complexity: This metric reflects the effort required to add new features to the application. A higher complexity score indicates a greater likelihood of encountering challenges and potential issues during development.
  2. Risk: This metric relates to the probability that adding new features may disrupt the operation of existing functionalities. A higher risk score suggests a greater vulnerability to bugs, regressions, and unintended consequences.
  3. Overall debt: This metric quantifies the additional work required when adding new features. It provides an overall assessment of the technical debt burden associated with the application.

By training ML models on manually analyzed data incorporating expert knowledge, we can accurately assess the technical debt level in applications even without prior knowledge. This enables organizations to comprehensively understand technical debt across their legacy software portfolio. With this information, IT leaders can make data-driven decisions about which applications to prioritize for modernization and how to allocate resources for technical debt reduction.

In addition to this ML-based approach, continuous monitoring of critical metrics, such as code complexity, code churn, and test coverage, can help identify potential hotspots where technical debt accumulates. By proactively addressing these issues, organizations can prevent technical debt from spiraling out of control and ensure their legacy applications’ long-term health and maintainability. Tracking the technical debt ratio (TDR) is also crucial, as it measures the amount spent on fixing software compared to developing it. A minimal TDR of less than five percent is ideal and can help demonstrate to executives the value of proactively addressing technical debt.

Conclusion

For machine learning to be a practical solution to measuring technical debt, it must be embodied in an intelligent, AI-driven, automated analysis tool that delivers comprehensive technical debt metrics and allows users to build a data-driven business case for modernizing a company’s suite of legacy apps. These metrics should identify the level of technical debt, complexity, and risk for each app and the legacy app portfolio.vFunction architectural observability platform is a purpose-built platform that embodies those principles. It uses AI and machine learning to provide accurate measures of technical debt and can also help automate the refactoring of legacy apps to eliminate technical debt. To see vFunction’s answer to how to measure technical debt in action, schedule a demo today.

From tangled to streamlined: New vFunction features for managing distributed applications

distributed application opentelemetry

Many teams turn to microservice architectures hoping to leave behind the complexity of monolithic applications. However, they soon realize that the complexity hasn’t disappeared — it has simply shifted to the network layer in the form of service dependencies, API interactions, and data flows between microservices. Managing and maintaining these intricate distributed systems can feel like swimming against a strong current — you might be making progress, but it’s a constant struggle and you are left tired. However, the new distributed applications capability in vFunction provides a life raft, offering much-needed visibility and control over your distributed architecture.

In this post, we’ll dive into how vFunction can automatically visualize the services comprising your distributed applications and highlight important architectural characteristics like redundancies, cyclic dependencies, and API policy violations. We’ll also look at the new conversational assistant powered by advanced AI that acts as an ever-present guide as you navigate vFunction and your applications.

Illuminating your distributed architecture

At the heart of vFunction’s new distributed applications capability is the Service Map – an intuitive visualization of all the services within a distributed application and their interactions. Each node represents a service, with details like name, type, tech stack, and hosting environment. The connections between nodes illustrate dependencies like API calls and shared resources.

OpenTelemetry

This architectural diagram is automatically constructed by vFunction during a learning period, where it observes traffic flowing through your distributed system. For applications instrumented with OpenTelemetry, vFunction can ingest the telemetry data directly, supporting a wide range of languages including Java, .NET, Node.js, Python, Go, and more. This OpenTelemetry integration expands vFunction’s ability to monitor distributed applications across numerous modern language stacks beyond traditional APM environments.

opentelemetry

Unlike traditional APM tools that simply display service maps based on aggregated traces, vFunction applies intelligent analysis to pinpoint potential architectural issues and surface them as visual cues on the Service Map. This guidance goes beyond just displaying nodes and arrows on the screen. It applies intelligent analysis to identify potential areas of concern, such as:

  • Redundant or overlapping services, like multiple payment processors, that could be consolidated.
  • Circular dependencies or multi-hop chains, where a chain of calls increases complexity.
  • Tightly coupled components like separate services using the same database, making changes difficult
  • Services that don’t adhere to API policies like accessing production data from test environments

These potential issues are flagged as visual cues on the Service Map and listed as actionable to-do’s (TODOs) that architects can prioritize and assign. You can filter the map to drill into specific areas, adjust layouts, and plan how services should be merged or split through an intuitive interface.

Your AI virtual architect

vFunction now includes an AI-powered assistant to guide you through managing your architecture every step of the way. Powered by advanced language models customized for the vFunction domain, the vFunction Assistant can understand and respond to natural language queries about your applications while incorporating real-time context.

vfunction ai powered assistant

Need to understand why certain domains are depicted a certain way on the map? Ask the assistant. Wondering about the implications of exclusivity on a class? The assistant can explain the reasoning and suggest the next steps. You can think of it as an ever-present co-architect sitting side-by-side with you.

You can query the assistant about any part of the vFunction interface and your monitored applications. Describing the intent behind a change in natural language, the assistant can point you in the right direction. No more getting lost in mountains of data and navigating between disparate views — the assistant acts as a tailored guide adapted to your specific needs.

Of course, the assistant has safeguards in place. It only operates on the context and data already accessible to you within vFunction, respecting all existing privacy, security and access controls. The conversations are ephemeral, and you can freely send feedback to improve the assistant’s responses over time.

An elegant architectural management solution

Together, the distributed applications visualization and conversational assistant provide architects and engineering teams with an elegant way to manage the complexity of different applications. The Service Map gives you a comprehensive, yet intuitive picture of your distributed application at a glance, automatically surfacing areas that need attention. The assistant seamlessly augments this visualization, understanding your architectural intent and providing relevant advice in real-time.

These new capabilities build on vFunction’s existing architectural analysis strengths, creating a unified solution for designing, implementing, observing, and evolving software architectures over time. By illuminating and streamlining the management of distributed architectures, vFunction empowers architects to embrace modern practices without being overwhelmed by their complexity.

Want to see vFunction in action? Request a demo today to learn how our architectural observability platform can keep your applications resilient and scalable, whatever their architecture.