Most development teams never check the licences on their dependencies. They run bundle install or npm install, the tests pass, and the code ships. Nobody thinks about licensing until a legal review surfaces a problem — and by then the dependency is woven into the codebase.
This has come up repeatedly in our team retrospectives. Across multiple client projects, we’ve found libraries with licences that look permissive at first glance but carry restrictions that can create real legal exposure for commercial software.
Why This Matters More Than You Think
Open source licensing is not a binary of “free” and “not free.” There’s a spectrum, and the dangerous part sits in the middle: licences that allow you to download the code, read it, even run it locally — but restrict how you can use it in production, especially in a commercial or SaaS context.
The problem is compounding. A typical Rails application has hundreds of gems. A Node.js project can have thousands of packages. Each one carries a licence, and each transitive dependency carries its own. Nobody reads them manually. Nobody checks whether that useful library pulled in three months ago switched from MIT to something more restrictive in a recent release.
This isn’t theoretical. Companies have received cease-and-desist letters. Others have been forced to open-source proprietary code or pay for commercial licences they didn’t budget for. The risk is real, and it scales with the size of your dependency tree.
The Three Licences You Need to Know About
Three licences in particular have caught teams off guard in recent years. They emerged as open source companies tried to protect their commercial interests, and each one carries restrictions that can surprise developers who assume “open source” means “free to use however you want.”
ELv2 (Elastic License 2.0)
Elastic introduced ELv2 when they relicensed Elasticsearch and Kibana in 2021. The licence permits most use, but it explicitly prohibits offering the software as a managed service. If you’re building a product that provides Elasticsearch functionality to your customers as a hosted service, you need a commercial agreement with Elastic.
The trap: ELv2 looks permissive. You can use the software internally. You can embed it in your product. But the moment your product starts to compete with the licensor’s own hosted offering, you’re in breach. The line between “using” and “competing” is not always clear, and that ambiguity is the risk.
AGPL (GNU Affero General Public License)
The AGPL is the network-aware version of the GPL. Standard GPL requires you to share source code if you distribute the software. AGPL extends this to network interaction: if users access your software over a network (which includes any web application), you must make your source code available to those users.
For SaaS products, this is significant. If you include an AGPL-licensed library in your web application, you may be required to release the entire application’s source code. Some legal interpretations are narrower than others, but the uncertainty alone is enough for most commercial projects to avoid AGPL dependencies entirely.
MongoDB was originally AGPL-licensed, which is one reason many companies opted for PostgreSQL instead. MongoDB later moved to the SSPL, which brings us to the third licence.
SSPL (Server Side Public License)
MongoDB created the SSPL when they felt the AGPL wasn’t strong enough to prevent cloud providers from offering MongoDB as a managed service. The SSPL requires that if you offer the software as a service, you must also open-source all the supporting infrastructure: the management tools, the monitoring, the backup systems, the hosting platform. Everything.
The Open Source Initiative does not recognise the SSPL as an open source licence. It’s closer to a source-available licence with conditions so broad that compliance is impractical for most commercial operations. If a dependency in your stack carries an SSPL licence, you need to understand exactly how you’re using it.
How to Check Your Dependencies
Manual checking doesn’t scale. You need tooling, and ideally that tooling runs in your CI/CD pipeline so problems are caught before they reach production.
For Ruby Projects
license_finder is the standard. It scans your Gemfile.lock, identifies every dependency’s licence, and lets you define an approved list. Any dependency with a licence not on the approved list fails the build.
gem install license_finder
license_finder
You configure it with a set of permitted licences (MIT, BSD, Apache 2.0, and so on) and it flags everything else for review. We run this on every Ruby project.
For Node.js Projects
license-checker provides similar functionality for npm packages:
npx license-checker --production --failOn "AGPL-3.0;SSPL-1.0"
For Python Projects
pip-licenses scans your virtual environment:
pip-licenses --fail-on="GNU Affero General Public License v3 (AGPLv3)"
CI/CD Integration
The critical step is making this automated. A licence check that someone remembers to run occasionally is not a licence check. Add it to your CI pipeline alongside your test suite and linting. If a new dependency introduces a restricted licence, the build fails and the team investigates before the code is merged.
This is cheap to set up — an hour of pipeline configuration — and it prevents problems that cost weeks or months to unwind later.
We run licence audits as part of every new project engagement and can scan an existing codebase in a day. If you are unsure what is in your dependency tree, that is exactly the right time to find out. Talk to us →
What to Do When You Find a Problem
Discovery is the easy part. The harder question is what to do when license_finder flags a dependency with a restrictive licence.
Assess the usage. Some licence restrictions only apply in specific contexts. AGPL is only triggered by network interaction. ELv2 only restricts competing services. If your usage doesn’t fall within the restricted scope, you may be fine — but get a clear legal opinion, not a developer’s best guess.
Look for alternatives. In many cases, there’s a permissively licensed library that does the same thing. Swapping out a dependency early is straightforward. Swapping one out after two years of tight integration is painful and expensive.
Negotiate a commercial licence. Many companies that use restrictive open source licences also offer commercial licences for a fee. If the library is genuinely the best tool for the job, paying for a commercial licence is often simpler than replacing it.
Remove and replace. If the library is deeply embedded, this becomes a small project in itself. The longer you wait, the more expensive it gets. This is the strongest argument for checking licences early and continuously.
Make It a Habit, Not an Afterthought
Replacing a deeply embedded AGPL dependency two years after integration is a multi-week project. Running license_finder in CI on day one is an hour of setup. The maths is straightforward, and the teams that get burned are always the ones who defer the check.
Run license_finder (or its equivalent) on every project. Add it to CI. Review the output when you add new dependencies. Treat a licence violation the same way you treat a failing test: fix it before you merge.
Licence auditing is one component of the broader code quality and security work we do for every client engagement — it fits naturally alongside dependency updates, vulnerability scanning, and CI hardening.
Book a dependency audit → — we will scan your dependencies and flag any issues before they become problems.
Frequently Asked Questions
Which open source licences are risky for commercial use? ELv2, AGPL, and SSPL each restrict commercial use in different ways. See the breakdown of all three earlier in this post.
How do we check what licences our dependencies use?
Use license_finder (Ruby), license-checker (Node.js), or pip-licenses (Python) in your CI pipeline. Setup takes about an hour.
What happens if we’re using a library with a restrictive licence? Your options are to replace the dependency, negotiate a commercial licence, or accept the terms. The cost of each rises the longer the library stays embedded.