💰I Built a Token Billing System for My AI Agent – Here’s How It Works

I’ve been building an AI agent that routes requests across multiple LLM providers, OpenAI, Anthropic etc., based on the task. But pretty quickly, I hit a real problem: how do you charge for this fairly?

Flat subscriptions didn’t make sense. Token costs vary by model, input vs output, and actual usage. A user generating a two-line summary isn’t the same as someone churning out 3,000-word articles, yet flat pricing treats them the same.

I looked at a few options for usage-based billing. Stripe Billing has metered subscriptions but you have to build your own token tracking pipeline on top. Orb and Metronome are good, but they’re separate vendors, you’d still need something to capture token data from your LLM calls and pipe it in. What I wanted was something at the gateway level, where the traffic already flows.

I ended up using Kong AI Gateway with Konnect Metering & Billing (built on OpenMeter). The gateway proxies every LLM request, so it already knows the token counts. The metering layer plugs directly into that. No separate vendor, no custom pipeline.

So instead of debating about pricing models, I set up the billing layer. A working system where every API request flows through a gateway, gets tracked, and is priced based on real usage:

  1. 🚧 Route requests through AI Gateway
  2. 🪙 Tokens get metered per consumer
  3. 💵 Pricing gets applied
  4. 🧾 Invoice generated

Here’s the whole setup, step by step.

  • Set up the gateway
  • Step 1: Create a consumer
  • Step 2: Configure the AI Proxy
  • Step 3: Enable token metering
  • Step 4: Create a feature
  • Step 5: Create a plan with a rate card
  • Step 6: Create a subscription
  • Step 7: Validate the invoice
  • Step 8: Connect Stripe

The Setup

The billing pipeline has three layers:

Kong AI Gateway proxies the LLM requests. It sits between the app and the provider, handles auth, and this is the part that matters for billing, it logs token statistics for every request.

Konnect Metering & Billing (this is built on OpenMeter) takes those token events and aggregates them per consumer, per billing cycle. It supports defining features, pricing models, and plans on top of the raw usage data.

Stripe collects payment. The metering layer generates invoices that sync to Stripe.

Let me walk through each piece.

Prerequisites

You can do this entirely through the UI or via CLI. I’ll cover both as we go.

  1. A Kong Konnect account
  2. An OpenAI API key (or any LLM provider key of your choice)

For CLI, you’ll also need decK (v1.43+) installed and a PAT from Kong Konnect.

Set Up the Gateway

Once you log in, click on API Gateway and create one.

I’m using Serverless here. You can choose Self-managed too. Enter the gateway name as ai-service and click Create and configure. Once that’s done, click Add a service and route and fill in:

  • Service Name: ai-service
  • Service URL: http://httpbin.konghq.com/anything
  • Route Name: ai-chat
  • Route Path: /chat

CLI

If you prefer the command line, generate your PAT and run:

export KONNECT_TOKEN='your_konnect_pat'
curl -Ls https://get.konghq.com/quickstart | bash -s -- 
  -k $KONNECT_TOKEN --deck-output

This gives you a running Kong Gateway connected to Konnect. It’ll output some environment variables, export them as instructed. You’ll also need:

export DECK_OPENAI_API_KEY='your_openai_api_key'

Then set up the service and route:

_format_version: "3.0"
services:
  - name: ai-service
    url: http://httpbin.konghq.com/anything
routes:
  - name: ai-chat
    paths:
      - "/chat"
    service:
      name: ai-service

Apply it with deck gateway apply. Now you have a route at /chat that we’ll wire up to an LLM.

Step 1: Create a Consumer

You can’t bill anyone if the gateway doesn’t know who is making the request. Consumers are how Kong identifies API callers. Later, we’ll map each consumer to a billing customer.

Add a consumer with a key-auth credential:

You can enter the Key value as acme-secret-key.

Now, you need to add the key-auth plugin to the service so the gateway actually requires authentication:

  1. Click on Plugins in the left sidebar
  2. Click on New Plugin
  3. Select Key Authentication from the plugin list
  4. Select Service as the scope or keep it as Global
  5. Click Save

CLI

_format_version: "3.0"
consumers:
  - username: acme-corp
    keyauth_credentials:
      - key: acme-secret-key

Then enable the key-auth plugin on the service so the gateway actually requires authentication:

_format_version: "3.0"
plugins:
  - name: key-auth
    service: ai-service
    config:
      key_names:
        - apikey

Apply both with deck gateway apply.

Now every request to /chat must include an apikey header. The gateway identifies the caller as acme-corp, and that identity flows through to metering. Without this step, usage events have no subject. They’re anonymous, and you can’t attribute them to anyone.

Step 2: Configure the AI Proxy

Next, wire the route to an actual LLM. The AI Proxy plugin accepts requests in OpenAI’s chat format and forwards them to the configured provider.

  1. Navigate to Plugins
  2. Click on New Plugin
  3. Select AI Proxy from the plugin list

Following the below yaml for CLI and configure the plugin fields accordingly:

_format_version: "3.0"
plugins:
  - name: ai-proxy
    config:
      route_type: llm/v1/chat
      auth:
        header_name: Authorization
        header_value: Bearer ${{ env "DECK_OPENAI_API_KEY" }}
      model:
        provider: openai
        name: gpt-4o
      logging:
        log_payloads: true
        log_statistics: true

Two things to note here:

log_statistics: true is what makes billing possible. Without it, the gateway proxies requests but doesn’t record token counts. When enabled, it captures prompt tokens, completion tokens, and total tokens on every response. This is the data that metering consumes downstream.

log_payloads: true logs the actual request/response content. This is optional and useful for debugging, but you’d probably turn it off in production for privacy reasons.

Apply with deck gateway apply and test:

curl -X POST "$KONNECT_PROXY_URL/chat" 
  -H "Content-Type: application/json" 
  -H "apikey: acme-secret-key" 
  --json '{
    "messages": [
      {"role": "system", "content": "You are a mathematician."},
      {"role": "user", "content": "What is 1+1?"}
    ]
  }'

You should get a response from GPT-4o. The gateway handled auth, forwarded the request, and logged the token statistics.

If you want to proxy multiple providers (say, OpenAI and Anthropic with automatic failover), you’d use [ai-proxy-advanced](https://developer.konghq.com/plugins/ai-proxy-advanced/) instead with a load balancing config. I stuck with a single provider here to keep the billing walkthrough focused.

Step 3: Enable Token Metering

Now we connect the gateway’s token logs to the metering system.

In Konnect, go to Metering & Billing in the sidebar. You’ll see an AI Gateway Tokens section. Click Enable Related API Gateways, select your control plane (the quickstart one), and confirm.

This activates a built-in meter called kong_konnect_llm_tokens. It uses SUM aggregation on the token count, grouped by:

  • $.model : which LLM handled the request
  • $.type : whether the tokens are input (request) or output (response)

The grouping matters because LLM providers charge differently for input vs. output tokens. Output tokens are typically 3-5x more expensive because input can be parallelized across GPUs while output generation is sequential, each token depends on all previous tokens. If your metering doesn’t split these, your pricing will be wrong.

At this point, every authenticated request through the AI Gateway generates a usage event that gets aggregated by the meter. But usage alone doesn’t generate invoices. You need to define what’s billable and how it’s priced.

Step 4: Create a Feature

A feature is the link between raw metered data and something that appears on an invoice. Without it, usage is tracked but never billed.

Go to Metering & Billing → Product Catalog → Features and create one:

  • Name: ai-token
  • Meter: AI Gateway Tokens
  • Group by filters:

    • Provider = openai
    • Type = request (this tracks input tokens; you’d create a separate feature for output tokens if you want to price them differently)

The filters narrow the meter to a specific slice of usage. In a real setup, you’d likely create multiple features, one per model, one per token direction, to apply different rates. For this walkthrough, I’m keeping it to one feature to show the flow.

Step 5: Create a Plan with a Rate Card

Plans bundle features with pricing. Go to Product Catalog → Plans and create one:

  • Name: Starter
  • Billing cadence: 1 month

Add a rate card:

  • Feature: ai-token
  • Pricing model: Usage Based
  • Price per unit: 1
  • Entitlement type: Boolean (grants access to the feature)

A note on what “price per unit” means here: 1 unit = 1 token, because the meter SUMs individual tokens. So entering 1 means $1.00 per token, which is way too expensive for real use. I’m using it here because the official tutorial does the same thing: a round number that makes invoice changes easy to spot during testing.

For production, you’d enter something like 0.000003 for GPT-4o input tokens ($3.00 per 1M tokens) or 0.00001 for GPT-4o output tokens ($10.00 per 1M tokens). There’s no “per 1,000” toggle in the UI. You do the math yourself and enter the per-token price as a decimal.

Publish the plan. It’s now available for subscriptions.

Step 6: Create a Customer and Start a Subscription

This is where the consumer from Step 1 connects to the billing system.

Go to Metering & Billing → Billing → Customers and create one:

  • Name: Acme Corp
  • Include usage from: select the acme-corp consumer

This mapping is what ties gateway traffic to a billable entity. The consumer handles identity at the gateway level; the customer handles identity at the billing level. They’re separate concepts joined here.

Now create a subscription:

  • Go to the Acme Corp customer, then Subscriptions → Create a Subscription
  • Plan: Starter
  • Start the subscription

One important detail: metering only invoices events that occur after the subscription starts. If you sent test requests before creating the subscription, those tokens won’t appear on any invoice. I spent some time confused by this before finding it in the docs.

Step 7: Validate the Invoice

Send a few requests through the gateway:

for i in {1..6}; do
  curl -s -X POST "$KONNECT_PROXY_URL/chat" 
    -H "Content-Type: application/json" 
    -H "apikey: acme-secret-key" 
    --json '{
      "messages": [
        {"role": "user", "content": "Explain what a Fourier transform does in two sentences."}
      ]
    }'
  echo ""
done

Wait a minute or two for the events to propagate, then go to Metering & Billing → Billing → Invoices. Click on Acme Corp, go to the Invoicing tab, and hit Preview Invoice.

You should see the ai-token feature listed with the aggregated token count and the calculated charge based on your rate card. That’s the billing pipeline working end to end, from an API request to a line item on an invoice.

Connecting Stripe

Konnect syncs invoices to Stripe, which handles payment collection, receipts, and retry logic for failed payments. You connect your Stripe account in the Metering & Billing settings, and invoices flow through automatically at the end of each billing cycle.

The result for end users is a transparent invoice showing exactly what they consumed: token count, model, rate applied. Not a flat fee with no breakdown.

## Things I Ran Into

The consumer-customer mapping confused me at first. Kong Gateway has “consumers” (API identity). Metering & Billing has “customers” (billing identity). They’re separate. You create both, then link them. If you skip the consumer or forget to link it, usage events come in but they’re not attributed to anyone billable. Set this up before you start sending traffic.

Input vs. output pricing is a bigger deal than I expected. Output tokens from OpenAI’s GPT-4o cost $10.00/1M vs. $2.50/1M for input. If you use a single flat rate for “tokens,” you’ll underprice output-heavy workloads significantly. Splitting features by token type (request vs. response) and pricing them separately is worth the extra configuration.

The order of operations matters. Specifically: create the consumer and link it to a customer before you start sending traffic you care about billing for. Events that arrive before a subscription exists don’t retroactively appear on invoices.

Where I’d Take This Next

This walkthrough uses a single provider and a single feature. A production setup would look more like:

  • Multiple features: one per model per token direction (GPT-4o input, GPT-4o output, Claude input, Claude output)
  • Tiered pricing: lower per-token rates at higher usage thresholds to incentivize growth
  • Entitlements with metered limits: cap total tokens per month per plan tier, so you can offer Starter (500K tokens), Pro (5M tokens), Enterprise (unlimited)
  • AI Proxy Advanced: route across multiple providers with load balancing (lowest-latency, round-robin, or cost-based routing)

The docs for all of these are at developer.konghq.com/metering-and-billing and developer.konghq.com/ai-gateway.

If you’re building an AI agent and thinking about how to charge for it, I’d be curious to hear your approach. Per-token, credits, flat rate? What’s working, what’s not? Drop your thoughts in the comments.

ORCHESTRATE v3.1 UAT — How AI Agents Tested Their Own Marketing Platform

ORCHESTRATE v3.1 UAT — How AI Agents Tested Their Own Marketing Platform

We just shipped v3.1 of the ORCHESTRATE marketing platform and ran a full User Acceptance Test — not with human testers, but with the same AI agents that built it.

What is ORCHESTRATE?

ORCHESTRATE is a multi-channel content publishing platform that manages LinkedIn pages, Reddit posts, Dev.to blogs, YouTube uploads, and Printify merch — all from a single MCP (Model Context Protocol) server. It runs 100+ tools across 10 capability areas, orchestrated by AI agents following a rigorous agile methodology.

The UAT Process

For Sprint 13, we ran the platform through its paces:

  1. Blog Publishing — Created and published articles to Dev.to via MCP tools
  2. Trending Topic Discovery — Scanned Reddit for trending AI/automation topics
  3. Product Promotion — Pulled real product mockups from our Printify store and created targeted LinkedIn posts
  4. Video Production — Generated a narrated YouTube video entirely through AI: script generation, Piper TTS narration, ffmpeg video assembly, and YouTube upload
  5. Cross-Platform Distribution — Published the same content across LinkedIn, Reddit, Dev.to, and YouTube simultaneously

The Tech Stack

  • Backend: Node.js REST API (port 3847) + MCP HTTP server (port 3848)
  • Frontend: React + Vite + Tailwind
  • AI Orchestration: MCP (Model Context Protocol) with 100+ registered tools
  • Audio: Piper TTS sidecar (port 8500) for narration
  • Video: ffmpeg in Docker for video assembly
  • Merch: Printify API integration for product management
  • Infrastructure: Docker Compose, single container deployment

Watch the UAT Video

We recorded the entire UAT experience as a narrated YouTube video:

The video was produced entirely by AI agents — from script generation to TTS narration to video assembly to YouTube upload.

What We Learned

Running UAT with AI agents revealed something interesting: the agents are better at systematic testing than ad-hoc exploration. They follow the acceptance criteria precisely, hit every endpoint, and document everything. But they don’t stumble onto edge cases the way a human tester might.

The solution? Combine AI-driven systematic UAT with human exploratory testing. Let the agents handle the regression suite while humans focus on the unexpected.

Try It Yourself

The ORCHESTRATE platform is built on open protocols (MCP) and standard tooling. If you’re building AI-powered content pipelines, the key insight is: treat your AI tools as first-class citizens in your CI/CD pipeline, not as ad-hoc helpers.

Shop merch: iamhitl.com
Follow the journey: I Am HITL on Dev.to

Microsoft ECIF Funding vs Other Cloud Incentives: Which One Delivers Real Value?

Adopting AI and cloud technologies is no longer optional—it’s essential for staying competitive. Yet, for many organizations, the biggest challenge isn’t strategy or technology—it’s the AI adoption cost. From infrastructure setup to skilled resources, the financial burden can slow down innovation.
This is where funding programs and cloud incentives come into play. Among them, Microsoft ECIF funding stands out as a strategic option. But how does it compare with other cloud incentives available in the market? More importantly, which one aligns best with your business goals?
Let’s explore.

What Is Microsoft ECIF Funding?
Microsoft ECIF funding (End Customer Investment Funds) is a program designed to help organizations accelerate their adoption of Microsoft technologies, especially AI and cloud solutions.
Unlike generic incentives, ecif funding is focused on delivering real business outcomes. It supports:
AI and cloud solution deployment
Proof of Concept (PoC) development
Microsoft Copilot adoption
Azure-based digital transformation initiatives
By reducing the AI adoption cost, ECIF enables businesses to move from idea to implementation faster and with less financial risk.

Understanding Other Cloud Incentives
Most cloud providers offer incentives to attract new customers and encourage platform usage. These typically include:

  1. Cloud Credits
    Free or discounted credits to explore services and run initial workloads.
  2. Startup and Innovation Programs
    Packages designed for startups that include credits, mentorship, and technical resources.
  3. Migration Support
    Financial incentives to help businesses shift from on-premise systems to the cloud.
  4. Training and Certification Offers
    Access to courses and certifications at reduced or no cost.
    While useful, these options are often broad and not always aligned with specific business outcomes.

Microsoft ECIF Funding vs Other Cloud Incentives
Let’s compare these options across key factors that matter to decision-makers.

Purpose and Strategic Focus
Microsoft ECIF funding is designed to support real-world implementation. It prioritizes projects that deliver measurable ROI, especially in AI adoption.
In contrast, other incentives often focus on onboarding and experimentation. They help you get started but may not support long-term execution.
👉 If your goal is to reduce AI adoption cost while achieving tangible outcomes, ecif funding offers a more strategic advantage.

Customization and Expert Support
One of the biggest strengths of Microsoft ECIF funding is its tailored approach. Businesses work with certified partners to design and execute solutions aligned with their goals.
Other cloud incentives are usually standardized. While they provide flexibility, they lack personalized guidance.
👉 This makes ecif funding ideal for organizations that need structured support and expertise.

Financial Impact and ROI
ECIF funding can cover a significant portion of project costs, reducing upfront investment and risk. It is designed to optimize long-term value.
On the other hand, most cloud incentives offer limited, short-term savings—such as credits that expire or only apply to specific services.
👉 For businesses concerned about AI adoption cost, ECIF delivers better long-term ROI.

Accessibility and Requirements
Other cloud incentives are easier to access. You can often sign up and start using them immediately.
However, Microsoft ECIF funding requires:
A defined project scope
A clear business use case
Collaboration with a Microsoft partner
👉 While this may seem complex, it ensures that funding is used effectively and delivers real impact.

Benefits of Microsoft ECIF Funding
Organizations leveraging Microsoft ECIF funding gain several advantages:
Accelerated Deployment: Faster implementation of AI and cloud solutions
Cost Optimization: Significant reduction in AI adoption cost
Lower Risk: Financial support minimizes experimentation risks
Expert Guidance: Access to experienced partners for execution
Scalable Solutions: Build solutions that grow with your business

Real-World Use Cases
Here’s how companies are using ecif funding to drive innovation:
Customer Support Automation
Deploy AI-powered chatbots to handle queries efficiently and reduce operational costs.
Data-Driven Decision Making
Build advanced analytics dashboards using cloud-based AI tools.
Workflow Automation
Automate repetitive processes to improve productivity and reduce manual effort.
Sales and Marketing Optimization
Use AI insights to personalize customer experiences and increase conversions.
In each case, Microsoft ECIF funding helps lower the AI adoption cost while delivering measurable business value.

When Should You Consider Other Cloud Incentives?
Other cloud incentives may be suitable if:
You are in the early exploration phase
You want to test multiple cloud platforms
You need quick access to free credits
However, these options are often limited when it comes to scaling and achieving long-term ROI.

How to Choose the Right Option
Before deciding, ask yourself:
Do I have a clear AI or cloud use case?
Am I focused on long-term ROI or short-term savings?
Do I need expert guidance for implementation?
Is reducing AI adoption cost a top priority?
If your answer leans toward structured growth and measurable outcomes, Microsoft ECIF funding is the better choice.

Conclusion: Invest Smartly in Your AI Future
Choosing between Microsoft ECIF funding and other cloud incentives is not just about cost—it’s about value. While other incentives can help you get started, ecif funding empowers you to scale, innovate, and achieve real business results.
It reduces the AI adoption cost, provides expert support, and ensures your investment delivers measurable ROI.

Take the Next Step
Ready to unlock the full potential of Microsoft ECIF funding?
Explore how your business can benefit from tailored funding opportunities or enhance your expertise with industry-recognized certifications.
👉 Visit Adoptify.ai to learn more about ECIF funding and certification programs—and start your journey toward smarter, faster AI adoption today.

Claude Code 소스코드를 뜯어봤다

더 많은 글은 radarlog.kr에서.

Claude Code의 소스코드가 유출됐다. TypeScript 파일 1,884개, 총 31MB.

누군가 이미 Mintlify로 깔끔한 문서 사이트를 만들어서 공개했는데, 거기에 정리된 환경변수는 30개다. 소스코드에는 195개 있다. 문서화된 슬래시 커맨드는 20개 남짓이다. 소스코드에는 80개 이상 있다.

문서에 없는 나머지는 뭘까. 직접 뜯어봤다.

소스코드의 전체 구조

압축을 풀면 src/ 하나에 모든 게 들어 있다. 게임 프로젝트처럼 폴더 구조가 역할별로 깔끔하게 나뉘어 있다.

src/
├── tools/          (2.8MB) — 40개의 도구 정의
├── components/     (9.5MB) — Ink 기반 터미널 UI
├── commands/       (2.8MB) — 80+ 슬래시 커맨드
├── services/       (1.9MB) — API, MCP, 분석, 컴팩트
├── hooks/          (1.3MB) — React 훅 (터미널 UI용)
├── utils/          (6.7MB) — 유틸리티 모음
├── constants/      (122KB) — 시스템 프롬프트, 상수
├── coordinator/    (23KB)  — 코디네이터 모드
├── buddy/          (79KB)  — 가상 펫 시스템 (!?)
└── voice/          (6.5KB) — 음성 모드

UE5 프로젝트의 Source/ 폴더를 보는 것 같다. 모듈 간 의존성이 깔끔하고, 각 도구가 독립적으로 분리되어 있다. tools/ 안에 40개 디렉토리가 각각 하나의 도구를 담당한다. 언리얼의 모듈 시스템이랑 느낌이 비슷하다.

런타임은 Bun이다. Node가 아니다. feature() 함수로 빌드 타임에 기능을 켜고 끄는 구조가 있는데, 이게 UE5의 WITH_EDITOR 같은 컴파일 플래그랑 정확히 같은 패턴이다.

const buddy = feature('BUDDY')
  ? require('./commands/buddy/index.js').default
  : null

feature('BUDDY')가 빌드 타임에 false로 평가되면 해당 코드가 번들에서 통째로 빠진다. Dead code elimination. UE5에서 #if WITH_EDITOR로 에디터 전용 코드를 빼는 것과 같다.

문서에 없는 슬래시 커맨드들

공식 문서에 나오는 커맨드는 /help, /compact, /config, /mcp 정도다. 소스코드에서 발견한 커맨드는 훨씬 많다. 그중 실제로 쓸 수 있는 것들을 추려봤다.

/btw — 사이드 질문. 메인 대화를 끊지 않고 빠른 질문을 던진다. immediate: true로 설정되어 있어서 대화 맥락을 오염시키지 않는다. 작업 중에 “btw 이 함수 뭐하는 거야?” 같은 질문을 던지기에 딱이다.

const btw = {
  type: 'local-jsx',
  name: 'btw',
  description: 'Ask a quick side question without interrupting the main conversation',
  immediate: true,
  argumentHint: '<question>',
}

/rewind — 코드 되돌리기. 대화와 코드를 이전 시점으로 되돌린다. alias가 /checkpoint다. Git의 특정 시점으로 돌아가는 게 아니라, Claude Code가 자체적으로 관리하는 체크포인트 시스템이다. 잘못된 방향으로 갈 때 “처음부터 다시”가 아니라 “여기서부터 다시”가 가능하다.

/compact — 컨텍스트 요약. 이건 문서에 나오지만, 인자를 받는다는 건 안 나온다. /compact 코드 변경사항 위주로 요약해줘처럼 요약 방향을 지정할 수 있다. 소스코드를 보면 customInstructions로 사용자 인자를 그대로 요약 프롬프트에 넘긴다.

/review — PR 코드 리뷰. gh CLI를 써서 PR diff를 가져온 다음 코드 리뷰를 해준다. PR 번호 없이 치면 열린 PR 목록을 보여준다.

const LOCAL_REVIEW_PROMPT = (args: string) => `
  You are an expert code reviewer. Follow these steps:
  1. If no PR number is provided, run `gh pr list`
  2. If provided, run `gh pr view <number>`
  3. Run `gh pr diff <number>` to get the diff
  4. Analyze the changes...
`

/advisor — 보조 모델 설정. 메인 모델 외에 “어드바이저” 모델을 따로 붙일 수 있다. /advisor opus로 설정하면 메인 모델이 작업할 때 Opus가 조언을 한다. 해제는 /advisor unset.

/stickers — 스티커 주문. 진짜로 Claude Code 스티커를 주문하는 페이지(stickermule.com/claudecode)를 브라우저에서 연다. 이스터에그인데, 소스코드에 떡하니 있다.

/sandbox — 샌드박스 토글. Bash 명령을 격리된 환경에서 실행하는 샌드박스 모드를 제어한다. macOS에서 사용 가능하고, 자동 허용 모드와 결합하면 안전하게 “다 허용”을 할 수 있다.

/fast — 빠른 모드. 더 빠른 모델로 전환한다. Claude AI 구독자와 API 사용자만 쓸 수 있고, isFastModeEnabled()로 게이트된다.

/effort — 노력 수준 조절. low, medium, high, max, auto 5단계. 간단한 질문에는 low, 복잡한 리팩토링에는 max. API 비용을 직접 제어할 수 있다.

/stats — 사용 통계. Claude Code 사용 패턴과 활동 통계를 보여준다.

/passes — 친구 초대. 무료 1주일 이용권을 친구에게 공유하고, 자신은 추가 사용량을 받는 레퍼럴 시스템이다. checkCachedPassesEligibility()로 자격을 확인한다.

/mobile — 모바일 앱 QR. alias가 /ios, /android다. QR 코드를 터미널에 표시해서 모바일 앱 다운로드를 안내한다.

/chrome — 크롬 확장 설정. Claude in Chrome 베타 기능을 설정한다. Claude AI 구독자만 사용 가능.

195개 환경변수 — 숨겨진 설정 표면

Mintlify 분석에서 문서화한 환경변수는 약 30개다. 소스코드에서 grep으로 찾은 CLAUDE_CODE_ 접두어 환경변수는 195개다.

전부 나열하진 않겠지만, 실전에서 유용한 것들이 있다.

CLAUDE_CODE_AUTO_COMPACT_WINDOW — 자동 컴팩트가 트리거되는 컨텍스트 윈도우 비율을 조절한다. 기본값보다 일찍 또는 늦게 컴팩트가 돌도록 할 수 있다.

CLAUDE_CODE_DISABLE_MOUSE — 마우스 입력을 완전히 끈다. tmux 안에서 Claude Code를 쓸 때 마우스 이벤트가 충돌하는 경우에 유용하다.

CLAUDE_CODE_SCROLL_SPEED — 스크롤 속도 조절. 터미널 환경에 따라 스크롤이 너무 빠르거나 느릴 때.

CLAUDE_CODE_TMUX_PREFIX — tmux 프리픽스 키 충돌을 해결한다. tmux 안에서 Claude Code의 키바인딩이 먹히지 않을 때 이걸로 조정한다.

CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING — 파일 체크포인팅을 끈다. /rewind에 쓰이는 체크포인트 시스템인데, 디스크 I/O가 부담될 때 끌 수 있다.

CLAUDE_CODE_COORDINATOR_MODE — 코디네이터 모드를 활성화한다. Claude가 직접 코드를 안 쓰고, 워커 에이전트를 지휘하는 오케스트레이터 역할만 한다. 이건 2편에서 자세히 다룬다.

CLAUDE_CODE_STREAMLINED_OUTPUT — 출력을 간소화한다. 도구 호출 과정 같은 중간 과정을 숨기고 결과만 보여준다.

CLAUDE_CODE_SYNTAX_HIGHLIGHT — 구문 강조를 제어한다. 터미널에서 색상이 깨질 때 끄면 된다.

CLAUDE_CODE_DISABLE_CRON — 크론 스케줄링을 끈다. Claude Code에 크론이 있다는 것 자체가 놀라운데, 이건 3편에서 다룬다.

# 실전 조합 예시 — tmux 안에서 가볍게 쓰기
export CLAUDE_CODE_DISABLE_MOUSE=1
export CLAUDE_CODE_STREAMLINED_OUTPUT=1
export DISABLE_AUTO_COMPACT=1

환경변수 중에는 CLAUDE_CODE_UNDERCOVER처럼 Anthropic 내부용으로 보이는 것도 있다. 이건 3편에서 다룬다.

키바인딩 — 커스터마이징이 된다

Claude Code의 키바인딩이 전부 커스터마이징 가능하다는 건 거의 알려지지 않았다. 소스코드에 defaultBindings.ts가 있고, 사용자 오버라이드를 keybindings.json에서 읽는다.

기본 키바인딩 중 쓸만한 것들이 많다.

// 글로벌
'ctrl+t': 'app:toggleTodos',     // 투두 리스트 토글
'ctrl+o': 'app:toggleTranscript', // 대화 전문 보기
'ctrl+r': 'history:search',       // 히스토리 검색

// 채팅
'shift+tab': 'chat:cycleMode',    // 모드 전환 (plan/code)
'meta+p': 'chat:modelPicker',     // 모델 선택
'meta+o': 'chat:fastMode',        // 빠른 모드 토글
'meta+t': 'chat:thinkingToggle',  // 사고 과정 표시 토글
'ctrl+s': 'chat:stash',           // 입력 스태시
'ctrl+g': 'chat:externalEditor',  // 외부 에디터로 열기

// 작업 중
'ctrl+b': 'task:background',      // 작업을 백그라운드로

ctrl+b로 현재 실행 중인 작업을 백그라운드로 보낼 수 있다. 에이전트가 긴 작업을 하고 있을 때, 끝날 때까지 기다리지 않고 다른 입력을 할 수 있다는 뜻이다. tmux에서는 ctrl+b를 두 번 눌러야 한다(tmux prefix와 겹치므로).

ctrl+s는 스태시다. git stash처럼, 지금 입력 중인 내용을 임시 저장하고 나중에 꺼낼 수 있다.

shift+up을 치면 메시지 액션 모드로 들어간다. 이전 메시지를 선택해서 복사하거나 다시 보낼 수 있다.

Windows에서는 VT 모드 지원 여부에 따라 shift+tab 대신 meta+m이 기본으로 바뀐다. 소스코드에서 Bun과 Node의 버전별 VT 모드 지원을 직접 체크하고 있다.

const SUPPORTS_TERMINAL_VT_MODE =
  getPlatform() !== 'windows' ||
  (isRunningWithBun()
    ? satisfies(process.versions.bun, '>=1.2.23')
    : satisfies(process.versions.node, '>=22.17.0 <23.0.0 || >=24.2.0'))

이런 수준의 플랫폼별 호환성 처리는 UE5에서 iOS/Android 크로스플랫폼 입력 처리할 때 보던 패턴과 똑같다.

macOS에서 잠들지 않는 이유

Claude Code가 작업 중일 때 맥이 잠들지 않는다. 운이 좋아서가 아니다. 소스코드에 caffeinate를 직접 호출하는 코드가 있다.

const CAFFEINATE_TIMEOUT_SECONDS = 300 // 5분
const RESTART_INTERVAL_MS = 4 * 60 * 1000 // 4분마다 재시작

// refCount 기반 — 작업이 0개가 되면 caffeinate를 끈다
export function startPreventSleep(): void {
  refCount++
  if (refCount === 1) {
    spawnCaffeinate()
  }
}

레퍼런스 카운팅 방식이다. 작업이 시작되면 카운트가 올라가고, 끝나면 내려간다. 카운트가 0이 되면 caffeinate 프로세스를 죽인다. 5분 타임아웃을 걸고 4분마다 재시작하는 이유는, Node 프로세스가 SIGKILL로 죽으면 cleanup 핸들러가 안 돌기 때문이다. orphan caffeinate가 5분 뒤 자동으로 죽는다.

게임 서버에서 keepalive 체크하는 것과 같은 패턴이다. 부모가 죽어도 자식이 무한히 살아남지 않도록, 자체 타임아웃을 건다.

다음 편 — 시스템 프롬프트와 코디네이터 모드

1편에서는 표면에 드러나는 숨겨진 기능들을 다뤘다. 2편에서는 더 깊이 들어간다. Claude Code의 시스템 프롬프트가 어떻게 조립되는지, 프롬프트 캐시를 깨지 않기 위해 어떤 구조를 쓰는지, 코디네이터 모드에서 워커 에이전트를 어떻게 지휘하는지. “AI가 AI를 관리하는” 아키텍처의 내부 구조다.

“Mintlify 문서에는 환경변수가 30개다. 소스코드에는 195개 있다.”

The Role of Communication in Brand Crises

Strategic Brand Communication

Brand communication is central to crisis management. Transparent, accurate, and timely communication helps organizations mitigate negative perceptions and fosters stakeholder trust.

Channels and Stakeholder Engagement

Organizations must carefully select communication channels to reach different stakeholders. Social media, press releases, and internal communication platforms all play a vital role in shaping public perception during crises.

My CSV had 50K rows. Row 23,487 broke everything.

My CSV had 50K rows. Row 23,487 broke everything.

Built a data processor for vendor CSV exports. Tested with sample files, looked good, pushed to production.

Two weeks later, 3 AM alert.

Vendor changed export format. Not the whole thing, just ONE field on random rows. They added an unquoted comma.

# Expected format
product_name,price,stock
Widgets,12.99,45

# Row 23,487
Widgets, Premium Edition,12.99,45

That comma shifted columns. Parser read “Premium Edition” as price, tried float conversion, crashed.

Spent an hour thinking it was my regex. Nope.

Thought maybe encoding issue. Nope.

Finally printed the raw row. There it was. Unquoted comma in product name field.

Tests missed it because first 20K rows were clean. Formatting bug only appeared when product names had certain keywords. My test CSVs had none of those.

No validation existed. Python csv module parsed it without error, so I assumed valid data. Bad assumption.

Fixed it:

import csv

def validate_row(row, expected_cols=3):
    if len(row) != expected_cols:
        return False, f"Expected {expected_cols} cols, got {len(row)}"

    try:
        float(row[1])  # price should be numeric
    except ValueError:
        return False, f"Not a number: {row[1]}"

    return True, None

with open('export.csv') as f:
    reader = csv.reader(f)
    next(reader)

    for i, row in enumerate(reader, start=1):
        valid, error = validate_row(row)
        if not valid:
            print(f"Row {i}: {error}")
            continue

        process_product(row)

Validate column count and types before processing. Log bad rows, skip them, don’t explode.

Should have tested with actual production data instead of clean samples. Dry run mode would have caught this without waking me up at 3 AM.

Do blockchains deform under agentic pressure?

Rheology studies how materials behave under sustained stress, creep, yield, structural shift. Invarians applies this framework to blockchain infrastructure.
The working hypothesis: as autonomous agents accumulate on-chain load, execution regimes don’t break, they migrate. Progressively. Structurally.
Since March 17, Labs has been tracking regime baselines across 6 L1×L2 pairs, updated hourly. Early observation on ETH × Optimism: 23% of windows already register S1D2, elevated demand pressure against a stable structural state. Correlation noted. Causality withheld.
The reference frame will expand to L1 × L2 × Bridge once bridge calibration is complete.
Two primitives are currently exposed to autonomous agents: Proof of Execution Context (PoEC) and Pattern Reference. A third is in development ε(t), a continuous measure of structural deformation as a function of agentic load over time.
If the hypothesis holds, ε(t) will be the first quantitative signal of how agents reshape the infrastructure they depend on.
Baselines are being recorded now. They cannot be reconstructed retroactively.
→ labs.invarians.com

blockchain #autonomousagents #infrastructure #web3 #onchain #agentic #ethereum

Why You Probably Don’t Need a Full-Time CTO

Consulting engagement vs fractional CTO - full-time overhead vs focused strategic decisions

The work I do now as a fractional CTO isn’t new. But it’s different from consulting in ways that matter.
I spent years at EY and Zilker Technology leading technical engagements — architecture direction, team building, platform migrations. Those were full engagements. Temporary, yes, but often 40+ hours a week. I’d make the architecture decisions, but I’d also be neck-deep in backlog grooming, PR reviews, data entry, and playing three roles because the engagement scoped it that way. The high-value work — the decisions, the direction, the “here’s how to architect this and why” — would take maybe 10-15 hours a week. The rest was overhead that cost the client more money but wasn’t the core focus.
I also did work that looked a lot closer to what fractional actually is: technical audits where I’d assess a system in a week and hand back a roadmap. Training drops where I’d come in, walk a team through how to move from Angular 1 to Angular 2, discuss the new paradigm, and leave them to execute. Architecture reviews where the deliverable was a set of diagrams and a handoff, not a six-month residency.
The difference with fractional is that you strip away the noise. No drowning in follow-up. No grooming the backlog or babysitting PRs. It’s the high-level direction, the diagrams, the team handoff, the “I’ve got an hour during lunch — show me what’s not working, I’ll build you a quick prototype, and we’ll walk through it.” The decisions, not the data entry. And the market agrees — demand for fractional C-suite roles grew 68% from 2023 to 2024, with the market now topping $5.7 billion globally.
What changed for me is that I started doing it independently. And the first thing I learned is that the companies who need this the most aren’t always the ones you’d expect.

Consulting engagement vs fractional CTO - full-time overhead vs focused strategic decisions

It’s Not Just Startups

The default narrative is that fractional CTOs exist for pre-seed startups that can’t afford a full-time hire. That’s part of it. But the pattern is broader.
At Hertz, DaVita, Kohl’s, and Chick-fil-A, the highest-value parts of my engagements were always the same: come in, assess, make the critical decisions, build the roadmap, coach the team on how to execute it. The companies had hundreds of engineers. They didn’t need another full-time executive. They needed someone who’d solved their specific problem before and could compress weeks of evaluation into days. Sometimes that turned into a full engagement where I built the team and led the delivery. But the direction-setting — the fractional part — was always the catalyst.
On the other end, I’m working with All That Technology, a home tech services company in the Dallas-Fort Worth metro. A small team — Mike runs the business with a few techs, building something real from a weekend side hustle. He’s competing against established players — companies with 100+ Google reviews, 40+ years in business, Yelp presence, the works. He didn’t need a CTO. He needed someone who could rebuild his Shopify storefront into a service-first conversion engine, set up PostHog analytics to separate bot traffic from real DFW customers, identify $53-119/month in wasted app spend, deliver 15+ strategy documents covering everything from an 8-week growth roadmap to pricing architecture to a 63-piece content calendar, build a growth strategy across Angie’s List, Nextdoor, and BBB, and build him SOPs for what to sell and how — discount structures that double as marketing (10% off for a Google review, another 10% for a social media share), subscription models for recurring revenue, and upsell frameworks so every service call becomes an opportunity to grow the relationship.
In 90 days, that business went from $81/month in revenue to $3,584/month. Average ticket size grew 2.3x. Orders started coming in from surrounding cities — customers finding him organically from towns he hadn’t specifically targeted yet. That growth started with zero ad spend — pure organic and referral. Google Shopping free listings alone are driving 45% of his traffic at $0. The repeat customer base is building — some customers coming back three, four times. We’re now layering in paid channels and the trajectory keeps climbing. The Shopify site generates leads that convert offline. He’s taking market share from competitors who have a decade-plus head start, and he’s doing it by being faster, more responsive, and better positioned online.
As Mike at All That Technology put it: “Your advice and guidance has helped iron out so many kinks — I regularly keep thinking I gotta keep up.” That’s the signal that the engagement is working. He’s not waiting for me to tell him what to do. He’s running harder because the direction is clear and the results are showing up.
That’s not architecture. That’s not CI/CD. That’s GTM strategy, marketing channel optimization, analytics, competitive positioning, pricing, and knowing enough about e-commerce platforms to build what the business actually needs instead of what a dev shop would sell you.

Small business growth through fractional CTO strategy - analytics, direction, and competitive positioning

What You’re Actually Buying

The technical decisions — stack, infrastructure, database, cloud provider — are the easy part. I wrote about this in What Does a CTO Actually Do?: any strong senior engineer can make those calls for $100 an hour. That’s commodity work.
What fractional gives you is the focused version of senior technical leadership — the decisions without the overhead. Your team, your offshore devs, your agentic workflows, or your three senior engineers can handle the execution. They need someone to set the direction, make the call on which way to go, and be available when they’re stuck. Not someone sitting in their standups.
What’s harder to buy by the hour:

  • Translation between engineering and business. Turning “we have significant technical debt” into “we have a time bomb that will cost us a full sprint to defuse, and here’s why now is cheaper than later.” Making sure neither side is talking past the other.
  • Pattern recognition from reps. I’ve done platform migrations, e-commerce rebuilds, real-time system architectures at scale, edge AI deployments, and mobile CI/CD before CI/CD was a thing — back when Chef was just becoming real and infrastructure meant being on a release call, not clicking a button in a cloud console. I’ve watched infra evolve from managing your own AS/400 to Infrastructure as Code with solid APIs and GUIs. When a client hits a problem I’ve seen before, the answer comes from experience across that entire arc, not research. That compresses timelines dramatically.
  • Business strategy that a pure technologist won’t give you. Marketing channels, pricing models, growth metrics, positioning against competitors. Not every fractional CTO does this. But the ones who’ve actually built and grown products — not just architected systems — bring a different lens. You might just need help with GTM, PMF, or figuring out which marketing channels are worth your time. I don’t have all the answers, but I’ve been through enough launches, growth experiments, and close-the-deal moments to help with positioning.
  • Honest assessment. I spend a lot of time saying “the data doesn’t support this yet.” It’s an unpopular sentence. But when your conversion rate drops 8% over a weekend on 300 visitors, that’s noise, not signal. Knowing when to act and when to wait is worth something.

The Cost Math (Done Honestly)

A senior CTO in a major metro commands $200-300K base plus equity. All-in with benefits, equipment, and the inevitable 2-month ramp-up, you’re looking at $250-350K annually. That’s before they make a single decision.
And that’s the best case. 40% of externally hired executives leave or are terminated within 18 months. When a CTO hire fails, the total cost — recruiting fees, severance, stalled strategy, team disruption, backfill — runs 200-400% of their annual salary. On a $250K hire, that’s $500K-$1M in real damage. And the executive search process takes 3-6 months before you even have someone in the seat.

Cost comparison between full-time CTO salary and fractional CTO engagement model

Fractional eliminates most of that risk. Bad fit? Adjust the engagement or part ways. No severance, no 6-month vacancy, no equity clawback drama.
Fractional doesn’t mean “the same job, fewer hours.” It means a fundamentally different engagement model. Typical fractional CTO rates run $150-500/hour depending on specialization and stage. Here’s what that actually looks like:
A quick distinction that matters here: not every new company is a “startup” in the venture-backed, 10x-growth sense. If you’re building a SaaS product and chasing product-market fit with the goal of raising a Series A, you’re a tech startup. If you started a home services company, a boutique agency, or an e-commerce shop and you’re building a real business that pays real bills — you’re a small business. You might call yourself a startup because you’re new, and you are, but the playbook is different. The technology needs are different. The budget is different. And the kind of help you need from a fractional CTO is different. Both are valid. But conflating them leads to bad advice.
SaaS / tech startup (pre-Series A, 1-5 engineers):
10-15 hours/week at $150-200/hr = $78K-156K/yr. You get the critical architecture decisions, CI/CD setup, mentorship for junior devs, and someone who’s done this before. You don’t get someone sitting in standups or writing JIRA tickets — and you shouldn’t want that at this stage.
Growth-stage tech company (Series A-B, 5-20 engineers):
15-20 hours/week at $200-300/hr = $156K-312K/yr. More hands-on. Sprint planning, hiring process design, vendor negotiations, 1:1s with senior devs. This is where concentrated experience earns its premium.
Non-technical founder / small business startup:
You started a real business — maybe it’s a service company, a local brand, an e-commerce shop. You don’t have engineers and might never need a full engineering team. But you need a website that converts, analytics that separate real customers from bot traffic, a growth strategy, and someone who can build the first version of whatever you need without charging you for a dev team. Project-based or low-hour retainer. A Shopify rebuild might be a fixed project. Ongoing growth strategy might be 5-10 hours/month. The cost is a fraction of hiring a technical co-founder, and you get someone who’s also thinking about your marketing, your analytics, and your unit economics — not just your code.
Enterprise / established companies:
Project-based or retainer. An architecture audit might be 40 hours total. A migration roadmap might be a 3-month engagement at 10 hours/week. A quarterly board-level technical review might be 8 hours per quarter. You have engineers. You need leadership for specific problems, not another VP.
The real savings aren’t in the hourly rate — they’re in the fact that most companies don’t need 2,080 hours of CTO per year. They need 500. Maybe 200. Maybe 40.

What Actually Fills Those Hours

With a startup client, a typical week:
Monday (3 hrs): Architecture review. PR reviews for anything touching infra, auth, or data models. Set technical direction for the week.
Wednesday (3 hrs): 1:1s with senior devs. Unblock technical decisions. Vendor evaluations if needed.
Friday (3 hrs): Sprint planning with eng lead. Technical debt prioritization. Security review.
Async (6 hrs): Slack, code reviews, documentation, incident response if critical.
With a small business client, it’s different:
Weekly check-in (1 hr): Review metrics — real traffic vs bots, conversion rates, revenue trends. Adjust strategy. Talk through what’s working in their outreach and what isn’t.
Async (3-5 hrs): Site improvements, SEO updates, analytics review, growth channel adjustments. Research on positioning. Draft pricing strategies or promotional campaigns.
Monthly: Deeper analysis. Are we hitting the 30/60/90 day targets? Where’s the next growth lever? What needs to change?
With an enterprise client:
Week 1: Deep-dive audit. Interview the team, read the code, map the architecture, identify the three things that will hurt worst in 12 months.
Week 2: Deliver findings. Prioritized roadmap. Specific recommendations with tradeoffs — not a 60-page deck, a working document the team can actually use.
Ongoing (if retained): Monthly check-in. Review progress against roadmap. Adjust priorities. Available for escalations. The team does the work — I make sure they’re doing the right work.

When Fractional Works (and When It Doesn’t)

Fractional is ideal when:

  • You’re a SaaS/tech startup pre-Series A with 1-5 engineers
  • Your core technical decisions haven’t been made yet
  • You need someone who’s done this before — not someone learning on your dime
  • You can’t yet justify a $250K+ salary
  • Your existing team is capable but needs strategic direction
  • You need an architecture audit, migration plan, or technical due diligence
  • You’re a non-technical founder who needs a technical translator
  • You’re a small business that needs both the tech and the growth strategy
  • You’re an enterprise that needs expert judgment for a specific initiative, not another FTE
    72% of CEOs plan to increase their use of fractional executives in 2025. That’s not startup desperation — that’s enterprise strategy.
    Go full-time when:
  • Engineering is 10+ people and needs daily leadership
  • Technical strategy is your primary competitive advantage
  • You’re post-Series B and have the runway
  • You need someone in the room for every product decision
  • You’re in a heavily regulated industry (healthcare, fintech, defense) where compliance requires constant CTO-level oversight
  • The coordination overhead of fractional starts exceeding the cost savings

The Hybrid Path

Most companies don’t need to make this an either-or decision. The smartest ones I’ve worked with start fractional and graduate to full-time when they actually need it.
Months 1-3: Establish architecture, CI/CD, coding standards. Make the big decisions. Build the foundation the team will live on for the next 2-3 years.
Months 4-6: Hire and mentor a senior engineer or eng manager. Transfer institutional knowledge. Start reducing your dependency on me.
Months 7-9: Reduce hours to advisory (5 hrs/week). The team should be self-sufficient for daily decisions.
Month 10+: Transition to board advisor or hire full-time CTO. Your architecture is solid, your team knows how to maintain it.
The fractional CTO can help write the job description for their full-time replacement, interview candidates, and ensure the transition doesn’t lose institutional knowledge. I’ve done this. It works because the incentives are aligned — my job is to make you successful, not to make myself permanent.
Not every engagement follows this arc. Some clients stay on a retainer indefinitely — the 5-10 hours/month of strategic oversight and growth coaching is exactly what they need. Others ramp up temporarily during a fundraise or product launch. The model flexes because the point was never to fill a chair. It was to solve problems.

The Bottom Line

82% of startup failures trace back to leadership and management issues. The question isn’t whether you need senior technical leadership — you absolutely do. The question is whether you need it 40 hours a week.
Don’t hire a full-time CTO because you think you should. Hire one because your engineering org is large enough to need daily strategic leadership. Until then, buy the decisions, not the seat.
And if what you actually need isn’t a CTO at all — if you need someone who can build the site, set up the analytics, figure out your growth channels, coach you on pricing, and help you go from side hustle to real business — that exists too. The title matters less than the outcome. You’ll still do the ground work. You’ll still be the one doing the outreach, handing out the review cards, closing the deals. But having someone in your corner who’s been through it — who can help you figure out what to measure, where to spend, and how to position — that changes the trajectory.
The best people I work with treat these engagements the same way: you’re paying for someone who’s made these mistakes before, so you don’t have to make them for the first time on your dime.
If you’re not sure which model fits, that’s a conversation worth having. No pitch, no pressure — just an honest assessment of where you are and what you actually need.
Book a call: https://cal.com/mdostal/meet

PostgreSQL Connection Pooling with PgBouncer: A Complete Guide

You launch your app. Traffic is light, everything works. A few weeks later you start seeing FATAL: remaining connection slots are reserved for non-replication superuser connections. Your PostgreSQL server is out of connections and your app is falling over.

This is one of the most common PostgreSQL scaling problems, and connection pooling is the fix. But the fix has its own complexity: PgBouncer has three modes with different tradeoffs, the configuration is full of footguns, and if you get it wrong you get subtle bugs that are much harder to debug than the original connection error.

This guide covers how PostgreSQL connections actually work, how to set up and configure PgBouncer correctly, and how to choose the right pool mode for your application.

Why PostgreSQL Connections Are Expensive

PostgreSQL handles each connection with a dedicated server process. When a client connects, Postgres forks a new OS process. That process:

  • Allocates its own memory (typically 5-10 MB per connection including shared memory overhead)
  • Maintains its own backend state, transaction state, and lock tables
  • Requires the kernel to schedule it like any other process

At 50 connections, this is fine. At 500 connections, you have 500 OS processes and the scheduler starts showing up in your performance profiles. At 1,000 connections, you are likely hitting the max_connections limit (default 100 in stock PostgreSQL) and your app is returning errors.

The naive fix is to increase max_connections. Don’t do that without thinking it through. Each connection costs memory. Set max_connections = 1000 on a server with 8 GB of RAM and you’ve allocated the entire heap to idle connections before a single query runs. The shared_buffers and work_mem math goes sideways fast.

The right fix is to reduce the number of actual connections to PostgreSQL. That’s what connection poolers do.

What PgBouncer Does

PgBouncer sits between your application and PostgreSQL. Your app thinks it’s talking to Postgres, but it’s actually talking to PgBouncer. PgBouncer maintains a pool of real connections to Postgres and hands them out to client requests.

The numbers look like this in practice:

  • Before PgBouncer: 300 app threads, 300 Postgres connections
  • After PgBouncer (transaction mode): 300 app threads, 20 actual Postgres connections

Those 20 connections serve 300 clients because most clients are not actually executing SQL at any given moment. They’re waiting for network I/O, processing results, or sitting idle. Transaction mode takes advantage of this by returning a connection to the pool the moment a transaction commits.

Installing PgBouncer

On Ubuntu/Debian:

sudo apt-get install pgbouncer

On macOS with Homebrew:

brew install pgbouncer

Configuring PgBouncer

A minimal working config:

[databases]
mydb = host=127.0.0.1 port=5432 dbname=mydb

[pgbouncer]
listen_addr = 127.0.0.1
listen_port = 6432
auth_type = scram-sha-256
auth_file = /etc/pgbouncer/userlist.txt
pool_mode = transaction
max_client_conn = 1000
default_pool_size = 25
min_pool_size = 5
reserve_pool_size = 5
server_idle_timeout = 600

For production, use hashed passwords. Generate them with:

SELECT concat('"', rolname, '" "', rolpassword, '"')
FROM pg_authid
WHERE rolname = 'myuser';

Your app connects to port 6432 instead of 5432. Nothing else changes in the app code.

The Three Pool Modes

Session Mode

A server connection is assigned when the client connects and held until the client disconnects. This is the safest mode, behaves identically to a direct PostgreSQL connection. Prepared statements, advisory locks, LISTEN/NOTIFY all work correctly.

Session mode does not help much with connection counts at steady state. Use it when you need full compatibility and your problem is peak load, not constant high concurrency.

Transaction Mode

A server connection is assigned for the duration of a transaction and returned to the pool immediately after. This gives you the dramatic reduction in server connections.

The tradeoff: session-level state does not persist across transactions. This breaks:

  • PREPARE and server-side prepared statement caching
  • SET commands that are not wrapped in a transaction
  • Advisory locks (session-scoped)
  • LISTEN and NOTIFY subscriptions
  • Temp tables that are supposed to persist across transactions

Transaction mode works well for stateless web applications using pg (Node.js), psycopg2/psycopg3 (Python), or JDBC (Java), as long as those frameworks don’t use session-level features.

Statement Mode

A connection is held only for a single SQL statement, then returned. Breaks multi-statement transactions entirely. Rarely the right choice for web applications.

Choosing Your Mode

Your app Recommended mode
Stateless API using ORM (Django, Rails, Prisma) Transaction
Long-lived connections with prepared statements Session
Connection count issues at peak only Session
Connection count issues at steady state Transaction
Serverless functions Transaction
Application using LISTEN/NOTIFY Session

Pool Sizing

A reasonable starting formula:

default_pool_size = (number of PostgreSQL CPU cores) * 2 + number of disks

In practice, 20-30 works well for most web applications. Check pool utilization while running:

SHOW POOLS;

cl_waiting > 0 sustained means the pool is undersized. sv_idle consistently high means it’s oversized.

Monitoring PgBouncer

Connect to the admin console:

psql -h 127.0.0.1 -p 6432 -U pgbouncer pgbouncer

Key commands: SHOW POOLS, SHOW STATS, SHOW CLIENTS, SHOW SERVERS, RELOAD.

SHOW STATS tells you avg_query_time and avg_wait_time. If either is climbing, something is backing up.

Common Pitfalls

Prepared statements in transaction mode: If your app uses server-side prepared statements, transaction mode will break it. Disable them in your driver: prepare_threshold=None in psycopg2, { prepare: false } in pg (Node.js).

Connection storms at startup: Set reserve_pool_size = 5 and max_client_conn to at least 2-3x your expected peak.

SSL: Always use SSL for both client-to-PgBouncer and PgBouncer-to-PostgreSQL in production.

When to Skip PgBouncer

You probably don’t need it if:

  • Fewer than 50 concurrent connections at peak
  • Using a modern ORM with client-side pooling already (Prisma, Django, Rails)
  • Serverless workloads with 1-2 connections per function instance

You need it if multiple processes or pods each maintain their own pool and the total exceeds max_connections.

Bottom Line

PostgreSQL connection pooling is not optional at scale. PgBouncer in transaction mode is the right default for most web applications.

The main things to get right: pool size (start at 20-30 for OLTP), mode (transaction for stateless apps, session for anything using prepared statements or advisory locks), monitoring (cl_waiting and avg_wait_time), and SSL in production.

Connection pooling is unglamorous infrastructure, but it’s the difference between an app that falls over at traffic spikes and one that just handles them.

Originally published at rivestack.io

Truthy and Falsy Values in JavaScript

Truthy and Falsy Values in JavaScript

  • In JavaScript, values used inside a condition are automatically converted into either true or false.
  • This concept is called Truthy and Falsy values.
  • It is very important in conditional statements like if, else, and while.

What are Truthy Values?

  • A truthy value is any value that JavaScript treats as true when used inside a condition.
    Examples of Truthy Values
1
-10
"Hello"
"CSK"
[]
{}
true

Example Program

let team = "CSK";

if (team) {
    console.log("Team exists");
}

Output

Team exists
  • Since “CSK” is a non-empty string, JavaScript treats it as true.

What are Falsy Values?

  • A falsy value is any value that JavaScript treats as false in a condition.

Falsy Values in JavaScript

  • There are only a few falsy values:
false
0
""
null
undefined
NaN

Example Program

let score = 0;

if (score) {
    console.log("Pass");
} else {
    console.log("No score");
}

Output

No score

  • Since 0 is a falsy value, the else block runs.

Simple Example

let name = "";

if (name) {
    console.log("Welcome");
} else {
    console.log("Enter your name");
}

Output

Enter your name
  • Because an empty string “” is falsy, JavaScript executes the else block.

Why is it Important?

Truthy and falsy values help in:

  • checking empty input fields
  • validating forms
  • checking login details
  • making decisions in programs

Conclusion
Truthy and falsy values are the foundation of decision making in JavaScript.