Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Usage Billing Webhook

A TypeScript backend system built with Bun, Hono, MongoDB/Mongoose, Redis, and BullMQ for usage-based billing, payment webhook processing, reconciliation workflows, and notification delivery.

This project is designed as a backend engineering portfolio project that models real industry backend infrastructure used in SaaS platforms, fintech systems, AI API products, notification platforms, developer APIs, and usage-based billing systems.

Core Purpose

Modern software platforms often need to:

  • Track customer usage.
  • Enforce quotas and plan limits.
  • Generate invoices from usage.
  • Receive and process payment webhooks.
  • Reconcile payment status when webhooks fail.
  • Notify customers about usage, invoices, payments, and failed actions.

This project implements those backend modules in a modular and production-aware way.

Main Modules

1. Billing Module

Handles:

  • API key creation.
  • Usage event tracking.
  • Usage counters.
  • Quota checks.
  • Invoice generation.
  • Invoice status updates.

Example usage events:

api.request
email.sent
sms.sent
payment.processed
storage.gb
ai.tokens
document.processed

2. Payments Module

Handles:

  • Payment intent creation.
  • Webhook receiving.
  • Webhook signature validation.
  • Duplicate webhook detection.
  • Payment status updates.
  • Webhook retry processing.
  • Payment reconciliation.

3. Notifications Module

Handles:

  • Notification template creation.
  • Email notifications.
  • SMS mock notifications.
  • In-app notifications.
  • Notification delivery tracking.
  • Failed notification retries.

Tech Stack

Layer Technology
Runtime Bun
Language TypeScript
HTTP Framework Hono
Database MongoDB
ODM Mongoose
Cache Redis
Queue BullMQ
Validation Zod
Logging Pino / JSON structured logging
Testing Bun Test
Docs Markdown + OpenAPI-ready structure
Architecture Vertical Slice Modular Monolith

Architecture

This project uses a Vertical Slice Modular Monolith.

That means:

  • The application is deployed as one backend.
  • Each business domain is isolated into its own module.
  • Each module owns its features, models, repositories, jobs, and types.
  • Each feature is kept readable without forcing developers to jump through too many files.

Instead of forcing this pattern for every endpoint:

route -> controller -> validator -> service -> repository -> model

this project uses feature files:

modules/billing/features/track-usage.feature.ts
modules/payments/features/receive-webhook.feature.ts
modules/notifications/features/send-notification.feature.ts

Each feature file owns the main request flow, while shared persistence logic stays in repositories.

Project Structure

src/
├── main.ts
├── app.ts
│
├── shared/
│   ├── config/
│   │   ├── env.ts
│   │   └── config.ts
│   ├── database/
│   │   └── mongoose.ts
│   ├── redis/
│   │   └── redis.client.ts
│   ├── queue/
│   │   └── bullmq.ts
│   ├── logger/
│   │   └── logger.ts
│   ├── errors/
│   │   └── app-error.ts
│   ├── middleware/
│   │   ├── error.middleware.ts
│   │   ├── request-id.middleware.ts
│   │   └── validate.middleware.ts
│   └── utils/
│       └── response.ts
│
└── modules/
    ├── billing/
    │   ├── billing.module.ts
    │   ├── billing.model.ts
    │   ├── billing.repository.ts
    │   ├── billing.types.ts
    │   ├── features/
    │   │   ├── create-api-key.feature.ts
    │   │   ├── track-usage.feature.ts
    │   │   ├── get-current-usage.feature.ts
    │   │   ├── generate-invoice.feature.ts
    │   │   └── mark-invoice-paid.feature.ts
    │   └── jobs/
    │       ├── aggregate-usage.job.ts
    │       └── generate-invoice.job.ts
    │
    ├── payments/
    │   ├── payment.module.ts
    │   ├── payment.model.ts
    │   ├── webhook-event.model.ts
    │   ├── payment.repository.ts
    │   ├── payment.types.ts
    │   ├── features/
    │   │   ├── create-payment-intent.feature.ts
    │   │   ├── receive-webhook.feature.ts
    │   │   ├── process-webhook.feature.ts
    │   │   ├── retry-webhook.feature.ts
    │   │   └── run-reconciliation.feature.ts
    │   └── jobs/
    │       ├── process-webhook.job.ts
    │       └── reconciliation.job.ts
    │
    └── notifications/
        ├── notification.module.ts
        ├── notification.model.ts
        ├── notification.repository.ts
        ├── notification.types.ts
        ├── features/
        │   ├── send-notification.feature.ts
        │   ├── create-template.feature.ts
        │   ├── retry-notification.feature.ts
        │   └── get-notifications.feature.ts
        └── jobs/
            └── send-notification.job.ts

Local Setup

Install dependencies

bun install

Environment variables

Create .env from .env.example:

cp .env.example .env

Start MongoDB and Redis

docker compose up -d

Run development server

bun run dev

Run tests

bun test

Core Backend Concepts Covered

This project demonstrates:

  • Usage metering.
  • Usage-based billing.
  • API key management.
  • Payment webhook processing.
  • Webhook idempotency.
  • Payment reconciliation.
  • Background jobs.
  • Redis queues.
  • Notification delivery.
  • Retry logic.
  • MongoDB/Mongoose persistence.
  • Zod validation.
  • Modular backend architecture.
  • Structured logging.
  • Error handling.
  • Operational runbooks.

Important Engineering Rules

1. Do not trust webhooks blindly

Every webhook must be verified before processing.

2. Webhooks must be idempotent

Duplicate webhook events must not double-process payments.

3. Money must be stored as integers

Use minor currency units.

Good:

amountInKobo = 500000

Bad:

amount = 5000.50

4. Usage tracking must be fast

Use Redis for fast counters and queues for async aggregation.

5. Notifications must be retryable

Failed email/SMS delivery should support retry and status tracking.

6. MongoDB is the source of truth

Redis is only for temporary counters, locks, queues, and cache.

Documentation

Suggested Scripts

{
  "scripts": {
    "dev": "bun --watch src/main.ts",
    "start": "bun src/main.ts",
    "test": "bun test",
    "lint": "biome check .",
    "format": "biome format --write ."
  }
}

About

A TypeScript backend built with Bun and Hono for usage-based billing, payment webhook processing, reconciliation jobs, and notification delivery.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages