9 min read
Kill Bill: open-source billing you run yourself
How Kill Bill works: the open-source billing and payments platform you self-host. Catalog, subscriptions, invoices, payment plugins, a Docker setup, your first subscription with the API, and when it beats Stripe Billing.
Every product that charges money ends up building the same thing: plans, trials, upgrades, invoices, failed card retries, refunds. Most teams rent that layer from Stripe Billing, Chargebee or Recurly and pay a percentage of revenue for it. Kill Bill takes the other road: it is an open-source billing and payments platform you deploy on your own infrastructure, released under the Apache 2.0 licence.
This note explains what Kill Bill is, how it works inside, how to run it locally and create your first subscription, and when it is (and is not) the right choice.
| Item | Details |
|---|---|
| What | Self-hosted subscription billing and payments server |
| Licence | Apache 2.0, free to use and modify |
| Stack | Java server, MySQL, MariaDB or PostgreSQL, REST API |
| Admin UI | Kaui, a back-office web app for finance and support |
| Gateways | Stripe, Adyen, PayPal, Braintree, GoCardless and more via plugins |
| Track record | More than 15 years in production |
| Links | Website · Docs · GitHub · API reference |
#The problem it solves
Hosted billing tools are fast to start with, but they come with three costs that grow over time:
- Fees that scale with revenue. A percentage of every invoice is cheap at 10k a month and painful at 10M.
- Lock-in. Your subscriptions, invoices and payment tokens live in someone else's system, shaped by their data model.
- Limited logic. If you need a local payment gateway, a different fraud provider, custom retry rules or invoices modified on the fly, you wait for the vendor's roadmap.
Kill Bill answers all three by being infrastructure you own. You pay for servers, not for revenue, the data sits in your database, and you can change behaviour with plugins.
The trade-off is honest: you now run a billing server. That means a database, upgrades, monitoring and developers who understand the model.
#The big picture
Kill Bill is not a checkout page or a customer portal. It is the billing engine behind your product. Your application calls its REST API when something happens (a customer signs up, upgrades, cancels), and Kill Bill takes care of everything that follows.
Drawing the diagram
- Kill Bill server. A Java application that exposes the REST API and runs the billing logic. One installation can host many tenants, each with its own data, catalog and configuration.
- Database. Every account, subscription, invoice, payment and audit log lives in your database. Nothing is kept in memory only.
- Kaui. The admin interface, so finance and support teams can look up customers, adjust invoices or issue refunds without touching the API.
- Plugins. Extension points loaded at runtime (OSGi bundles) that connect gateways and tax engines or change how invoices, payments and the catalog behave.
- Events. Kill Bill notifies your application when something changes, for example an invoice was created or a payment failed, so you can grant access or send an email.
- Client libraries. Official clients exist for Java, Ruby, PHP, Node.js, Python and Go.
#Core concepts
| Concept | What it means |
|---|---|
| Tenant | An isolated space with its own API key and secret. Useful for environments or white-label platforms |
| Account | A customer: name, email, currency, time zone, payment methods |
| Catalog | Your pricing model: products, plans, prices, billing periods and phases |
| Plan phase | A stage in a plan, such as a 14-day TRIAL followed by an EVERGREEN paid phase |
| Subscription | The contract between an account and a plan; it moves through phases automatically |
| Bundle | A group of subscriptions, such as a base plan and its add-ons |
| Invoice | Generated for each billing cycle, with recurring, fixed, usage, credit and proration items |
| Payment | The attempt to collect an invoice through a payment method and its plugin |
| Overdue | Dunning rules that change an account's state (warning, blocked) when invoices stay unpaid |
The catalog deserves a note. It is usually an XML file (validated against a published schema), and it is where Kill Bill is most powerful: trials, discount phases, add-ons, upgrade and downgrade rules, multiple currencies and price lists all live there. For experiments you can skip the XML and create simple plans through the API or in Kaui.
#The life of a subscription
Take a customer who signs up for a "Pro" plan with a 14-day trial at 29 USD a month.
Drawing the diagram
- Sign up. Your app creates an account, attaches a payment method and creates a subscription to
pro-monthly. - Trial. Kill Bill starts the
TRIALphase and produces a zero-amount invoice. Nothing is charged. - Phase change. On day 15 the subscription moves to the
EVERGREENphase on its own. No cron job on your side. - Invoice. At every billing cycle Kill Bill builds the invoice, including prorations if the customer upgraded mid-cycle, credits and usage charges.
- Payment. The invoice triggers a payment on the default payment method, through the gateway plugin.
- Failure handling. If the card is declined, retries and overdue rules take over, and they can move the account to a warning or blocked state that your app reads to restrict access.
- Events. At each step your app receives notifications it can act on.
#Run it locally with Docker
The quickest setup uses Docker Compose with three containers: Kill Bill, Kaui and a MariaDB database shared by both. Save this as docker-compose.yml (these are the image versions from the official getting-started guide; check Docker Hub for newer tags):
version: '3.2'
volumes:
db:
services:
killbill:
image: killbill/killbill:0.24.16
ports:
- "8080:8080"
environment:
- KILLBILL_DAO_URL=jdbc:mysql://db:3306/killbill
- KILLBILL_DAO_USER=root
- KILLBILL_DAO_PASSWORD=killbill
- KILLBILL_CATALOG_URI=SpyCarAdvanced.xml
kaui:
image: killbill/kaui:4.0.4
ports:
- "9090:8080"
environment:
- KAUI_CONFIG_DAO_URL=jdbc:mysql://db:3306/kaui
- KAUI_CONFIG_DAO_USER=root
- KAUI_CONFIG_DAO_PASSWORD=killbill
- KAUI_KILLBILL_URL=http://killbill:8080
db:
image: killbill/mariadb:0.24
volumes:
- type: volume
source: db
target: /var/lib/mysql
expose:
- "3306"
environment:
- MYSQL_ROOT_PASSWORD=killbillThen start everything:
docker compose up- Startup takes a couple of minutes. If a container crashes, give Docker at least 4 GB of memory.
- Kaui runs at
http://127.0.0.1:9090with the default loginadmin/password. - The API explorer runs at
http://127.0.0.1:8080/api.html. - These credentials are for local testing only. Change them before anything leaves your machine.
#Your first subscription with the API
With the stack running, these calls create a tenant, a simple plan, a customer and a subscription. Every request after the tenant uses the tenant's API key and secret as headers.
KB=http://127.0.0.1:8080
AUTH=(-u admin:password -H "X-Killbill-ApiKey: bob" -H "X-Killbill-ApiSecret: lazar")
JSON=(-H "Content-Type: application/json" -H "X-Killbill-CreatedBy: demo")
# 1. Create a tenant (isolated space with its own key and secret)
curl -X POST -u admin:password "${JSON[@]}" \
-d '{"apiKey": "bob", "apiSecret": "lazar"}' \
"$KB/1.0/kb/tenants"
# 2. Create a simple plan: Pro, 29 USD monthly, 14-day trial
curl -X POST "${AUTH[@]}" "${JSON[@]}" \
-d '{"planId": "pro-monthly", "productName": "Pro", "productCategory": "BASE",
"currency": "USD", "amount": 29, "billingPeriod": "MONTHLY",
"trialLength": 14, "trialTimeUnit": "DAYS"}' \
"$KB/1.0/kb/catalog/simplePlan"
# 3. Create a customer account (the new id is in the Location header)
curl -i -X POST "${AUTH[@]}" "${JSON[@]}" \
-d '{"name": "Jane Doe", "email": "jane@example.com", "currency": "USD"}' \
"$KB/1.0/kb/accounts"
ACCOUNT_ID=paste-the-id-here
# 4. Add a default payment method (external payment, for testing)
curl -X POST "${AUTH[@]}" "${JSON[@]}" \
-d '{"pluginName": "__EXTERNAL_PAYMENT__"}' \
"$KB/1.0/kb/accounts/$ACCOUNT_ID/paymentMethods?isDefault=true"
# 5. Subscribe the account to the plan
curl -X POST "${AUTH[@]}" "${JSON[@]}" \
-d "{\"accountId\": \"$ACCOUNT_ID\", \"planName\": \"pro-monthly\"}" \
"$KB/1.0/kb/subscriptions"
# 6. See the invoice Kill Bill generated
curl "${AUTH[@]}" "$KB/1.0/kb/accounts/$ACCOUNT_ID/invoices"You should see a zero-amount trial invoice. Open the same account in Kaui to see its subscription, invoices and timeline. In production your backend makes these calls through one of the client libraries rather than curl, and a real gateway plugin replaces the external payment method.
#Plugins: where the flexibility lives
Kill Bill's real power is building your own logic on top of the core. Plugins come in several types:
| Plugin type | What it can do |
|---|---|
| Payment | Connect a gateway or processor (Stripe, Adyen, PayPal, Braintree, GoCardless, or your own) |
| Payment control | Run code before and after a payment: routing, fraud checks, retry rules, aborting a charge |
| Invoice | Add or change invoice items on the fly, such as taxes or custom fees |
| Catalog | Load pricing from your own system instead of XML |
| Usage | Feed usage data for in-arrear or consumption billing |
| Entitlement | Intercept subscription changes, for example to validate an upgrade |
| Notification | React to Kill Bill events and push them to other systems |
Open-source plugins already cover common needs such as tax providers (AvaTax), email notifications and analytics, and they double as examples when you write your own. Plugins are installed with KPM, the Kill Bill package manager, or from Kaui.
#Open source or Aviate?
Both are built on the same open-source core.
| Open source | Aviate | |
|---|---|---|
| Price | Free | Fixed price, not a share of revenue |
| Hosting | You run it (Docker, Kubernetes, AWS, Tomcat) | Managed cloud with auto-scaling and monitoring |
| Extras | Core billing, payments, Kaui, plugins | Catalog API, metering, wallet and credits, coupons, tax |
| Support | Community (Google Group) | Commercial support |
A few Aviate features, such as usage metering and prepaid wallets, target usage-based and AI token billing. Because the core stays open source, the project stresses that you can move away without losing your data.
#When Kill Bill is the right choice
Good fit:
- Your billing volume makes percentage fees expensive.
- You need gateways, fraud tools or tax providers that hosted tools do not support, which is common outside the US and Europe.
- You need custom decision logic: dynamic amounts, payment routing, unusual retry policies.
- Billing data must stay in your own infrastructure for compliance or data sovereignty.
- You run a platform that bills on behalf of many tenants.
Poor fit:
- You are pre-launch and need billing working this week. Stripe Billing, Paddle or Lemon Squeezy will be faster.
- Your model is simple subscriptions on a single gateway.
- Nobody on the team can own a Java service, a database and its upgrades.
- You want a hosted checkout page and customer portal out of the box. With Kill Bill you build those.
#My take
Kill Bill is what billing looks like when you treat it as infrastructure instead of a feature. The model is explicit (catalog, phases, bundles, invoices, overdue states), every state change is audited, and the plugin system lets you change behaviour without forking. The cost is operational: you inherit a real server with a real data model, and the catalog has a learning curve.
My rule of thumb: start with a hosted tool while pricing is still changing every month, and design your own code so billing sits behind an interface. When fees, gateway coverage or custom rules start to hurt, Kill Bill is one of the very few mature, open-source options you can move to.
#FAQ
Is Kill Bill really free?
Yes. The core is open source under the Apache 2.0 licence. You pay only for your own infrastructure, or for Aviate if you want the managed version and extra features.
Does Kill Bill replace Stripe?
No. Kill Bill replaces the billing layer (plans, subscriptions, invoices, dunning). Payments still go through a gateway such as Stripe, Adyen or PayPal, connected through a plugin.
Which languages can I use to integrate it?
Any language that can call a REST API. Official client libraries exist for Java, Ruby, PHP, Node.js, Python and Go.
Which databases does it support?
The core team uses MySQL and also tests against MariaDB and PostgreSQL. The Docker setup ships with MariaDB.
Can it handle usage-based or AI token billing?
Yes. The open-source core supports usage and in-arrear billing, and Aviate adds metering, prepaid wallets and credits aimed at usage-based and AI products.
Does Kill Bill include a checkout page or customer portal?
No. It is a back-end engine with an admin UI (Kaui). Your application provides the customer-facing checkout and account pages and calls the API.
#Links
- Website: killbill.io
- Documentation: docs.killbill.io
- Getting started: docs.killbill.io/latest/getting_started
- API reference: apidocs.killbill.io
- Source code: github.com/killbill/killbill
- Community: Kill Bill users Google Group
Did this land?
Conversation
Building something like this?
Tell me what you are working on. I reply within a day.