Our website uses cookies to enhance your browsing experience.
Accept
to the top
>
>
Avoid adding new library to project:...

Avoid adding new library to project: 10-year retrospective

Sep 02 2026
Author:

Everyone is trying to speed up software development by building their solutions using "bricks" like third-party components or libraries. However, we forget what problems they may trigger. Today, I'll try to explain why it's worth thinking twice before adding a new dependency to a project. The article is a remake that I've decided to write after realizing that my old recommendation is still relevant.

Ten years ago, I've said about it in the compilation of recommendations "The Ultimate Question of Programming, Refactoring, and Everything."

Many people criticized this point, which made me doubt whether I was right. After all, the world doesn't stand still: progress marches on. Developers put apps together like LEGO bricks, and plus, package managers have evolved. It's convenient for everyone, and everyone seems happy. So why am I bringing up my doubts?

I've not mentioned this topic again in later articles, including 60 terrible tips for a C++ developer (2023), but I've been watching how things have changed for several years, and I can say that my position has returned to what it was before: whenever possible, it's still better to avoid to add new libraries that spawn more dependencies.

And I think I was right, although to be honest, I've chosen not the best way to present this or not the best examples. Plus, the earlier arguments omit an important point that has come to the fore in the context of secure software development and certification. Actually, there is one, number 4, but it sounds too trivial. So let me try again.

First, I'll show an older, slightly reduced version of the text, and then I'll reinforce it with new arguments and thoughts. Overall, everything I've said still stands, and I ask that you think about what you've read before we get into another round of arguments in the comments :)

Chapter 41 from the 2016 collection of tips

Suppose you need to implement an X functionality in your project. Theorists of software development will say that you have to take the already existing library Y, and use it to implement the things you need. In fact, it is a classic approach in software development, reusing your own or others' previously created libraries (third-party libraries). And most programmers use this way.

However, those theorists in various articles and books, forget to mention what hell it will become to support several dozen third-party libraries in about 10 years.

I strongly recommend avoiding adding a new library to a project. Please don't get me wrong. I am not saying that you shouldn't use libraries at all, and write everything yourself. This would be insufficient, of course. But sometimes a new library is added to the project at the whim of some developer, intending to add a little cool small "feature" to the project. It's not hard to add a new library to the project, but then the whole team will have to carry the load of its support for many years.

Tracking the evolution of several large projects, I've seen quite a lot of problems caused by a large number of third-party libraries. I will probably enumerate only some of the issues, but this list should already provoke some thoughts:

  • Adding new libraries promptly increases the project size. In our era of fast Internet and large SSD drives, this is not a big problem, of course. But, it's rather unpleasant when the download time from the version control system turns into 10 minutes instead of 1.
  • Even if you use just 1% of the library capabilities, it is usually included in the project as a whole. As a result, if the libraries are used in the form of compiled modules (for example, DLL), the distribution size grows very fast. If you use the library as source code, then the compile time significantly increases.
  • Infrastructure connected with the compilation of the project becomes more complicated. Some libraries require additional components. A simple example: we need Python for building. As a result, in some time you'll need to have a lot of additional programs to build a project. So the probability that something will fail increases. It's hard to explain, you need to experience it. In big projects something fails all the time, and you have to put a lot of effort into making everything work and compile.
  • If you care about vulnerabilities, you must regularly update third-party libraries. It would be of interest to violators, to study the code libraries to search for vulnerabilities. Firstly, many libraries are open-source, and secondly, having found a weak point in one of the libraries, you can get a master exploit to many applications where the library is used.
  • One the libraries may suddenly change the license type. Firstly, you have to keep that in mind, and track the changes. Secondly, it's unclear what to do if that happens. For example, once, a widely used library softfloat moved to BSD from a personal agreement.
  • You will have troubles upgrading to a new version of the compiler. There will definitely be a few libraries that won't be ready to adapt for a new compiler, you'll have to wait, or make your own corrections in the library.
  • You will have problems when moving to a different compiler. For example, you are using Visual C++, and want to use Intel C++. There will surely be a couple of libraries where something is wrong.
  • You will have problems moving to a different platform. Not necessarily even a totally different platform. Let's say, you'll decide to port a Win32 application to Win64. You will have the same problems. Most likely, several libraries won't be ready for this, and you'll wonder what to do with them. It is especially unpleasant when the library is lying dormant somewhere, and is no longer developing.
  • Sooner or later, if you use lots of C libraries, where the types aren't stored in namespace, you'll start having name clashes. This causes compilation errors, or hidden errors. For example, a wrong enum constant can be used instead of the one you've intended to use.
  • If your project uses a lot of libraries, adding another one won't seem harmful. We can draw an analogy with the broken window theory. But consequently, the growth of the project turns into uncontrolled chaos.
  • And there could be a lot of other downsides in adding new libraries, which I'm probably not aware of. But in any case, additional libraries increase the complexity of project support. Some issues can occur in a fragment where they were least expected to.

Again, I should emphasize; I don't say that we should stop using third-party libraries at all. If we have to work with images in PNG format in the program, we'll take the LibPNG library, and not reinvent the wheel.

But even working with PNG we need to stop and think. Do we really need a library? What do we want to do with the images? If the task is just to save an image in *.png file, you can get by with system functions. For example, if you have a Windows application, you could use WIC. And if you're already using an MFC library, there is no need to make the code more sophisticated, because there's a Cimage class (see the discussion on Stack Overflow). Minus one library—great!

Recommendation

Keep resisting the temptation to add new libraries to your project. Add it only when you're sure that libraries are really indispensable.

What to do? Here are some possible maneuvers:

  • Check your system's API or one of the libraries you're already using whether it has this functionality.
  • Implement the functionality by yourself if it's not so huge instead of using only a very small part of the library's functionality. The argument that "I add the whole library and maybe it'll be handy someday in the future" isn't worth the trouble. Usually it doesn't happen. Yes, programmers are too focused on versatility, which often isn't needed.
  • Choose the simplest library that meets your requirements and helps you solve the task. As mentioned above, don't choose a more powerful library "just in case."
  • Just wait a moment and think over before adding the library. Have some tea, take a break, and discuss the task with your colleagues. You may find that you don't need a third-party library after all and can solve the problem another way.

P.S. Many people won't like what is said here. For example, I recommend using WinAPI rather than a non-portable universal library. It kind of locks the project into a single operating system and complicates the further program migration—and I can't agree with this point. This idea to migrate the program to another OS is just sitting in the developer's head, but in reality, management may never set such a goal at all, or the project will fail due to excessive complexity and versatility, even before it gains popularity and the need for porting arises. Also, don't forget item (8) on the list of issues provided above.

The end of the old post, but not the end of the story

Everything said in the original is still true today, although the emphasis has shifted. Today, we need to focus on controlling an overly gigantic codebase when establishing secure development processes. Now it is coming to the forefront. Point number 4 has become truly urgent.

Adding libraries in your projects triggers the creation of transitive dependencies. This means that the library uses other libraries, which in turn use other libraries, and so on. Now the required 10 libraries for your projects, in reality, turn into 100s being used. In some languages, such as C++, this is not very noticeable, whereas when developing in JavaScript, Java, or Python, huge chains of dependencies quickly emerge.

If a vulnerability is detected in one of these libraries, it means your application is also potentially vulnerable. It doesn't matter to the user whether your app is vulnerable because of your own code or third-party code.

Of course, the vulnerability in a particular library doesn't automatically mean that your application is vulnerable as well. Dangerous functions may simply never be called, or work with data that won't cause any problems. This means that the vulnerability isn't the primary attack target.

However, that doesn't make it much easier. After all, we need to be sure that the vulnerability can't be exploited. And in reality, it can be really hard work.

So, if you think about your project's reputation, it's worth tracking all new vulnerabilities in all components that are used directly or indirectly, for example, using Software Composition Analysis (SCA) tools for this purpose.

If you have composition analysis tools, what's the problem with having a large number of dependencies? The more there are, the greater the chance that someone will find a new vulnerability and exploit it.

That's not all. Vulnerabilities may be caused not only by a random bug, but can also be the intentional act. For example, supply chain attacks become more well-known problem: attackers use various methods to inject undocumented features into various open-source libraries. For example, they contribute some changes and enhancements for a while, build up a positive reputation, and then sneak a backdoor into the code. Transitive dependencies open the door to exploit a large number of applications at once. So, the more third-party libraries you use, the higher the risk of supply chain attacks.

Another option of such an attack has emerged related to AI-generated code (GenAI). AI can hallucinate in the names of the required packages. It's clear that hallucinations follow certain patterns, and malicious actors will not miss the opportunity and use it: they create and publish compromised packages with names that GenAI is most likely to hallucinate. It sounds far-fetched, but it works, and such attacks have already been used. They came to be known as slopsquatting.

The next topic is static analysis. From a security standpoint, you should review your own code plus all third-party code. Few people do this, since most people tend to focus only on viewing their own code. But anyone who stops to think about it is faced with a huge amount of work.

However, if you want to conduct certification testing on your project, it makes no difference whether you wrote the code yourself or obtained it from an external source. Do you use third-party code? It's yours now. Take responsibility for it. That makes sense: it doesn't matter who wrote the code that makes the app vulnerable.

In practice, it may be impractical for a single company to perform a static analysis of all borrowed code. This has given rise to trusted repository projects and consortia of companies for the conjoint analysis of borrowed components. One approach is to analyze the initial modules that make up the attack surface. Here again, the problem of defining this surface arises. I won't go into detail here.

Conclusion

Of course, it won't impact on our habit to eagerly add third-party components into the project. I'm not calling to change that; it'd be counterproductive. However, I still want you to be aware of the potential problems you might encounter.

I think you can try a little bit enhance your code review process by controlling (or discussing) all libraries that are added. Let the developer explain why they really need yet another library. Perhaps, if they have known this during the development phase, they would have chosen a different approach to solving the problem or used the functionality of another library that was already included in the project. In short, try to avoid adding new libraries to the project. Maybe it'll actually work out for you someday :) And you will thank me later.

Ideally, it would be a good idea to audit your project from time to time to check whether all project-related libraries are being used. I've seen cases where, while porting a large C++ application from Win32 to Win64, it turned out that about 10 libraries weren't being used at all. At the same time, resources had been spent for many years on maintaining them within the project. Conducting such an audit may not be easy, but you might be able to pull it off.

Subscribe to the newsletter
Want to receive a monthly digest of the most interesting articles and news? Subscribe!

Comments (0)

Next comments next comments
close comment form