npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@rodnoycry/ydb-faas

v2.0.0

Published

Bridges YDB's per-invocation driver requirement in FaaS environments (AWS Lambda, Yandex Cloud Functions, Vercel Functions) with libraries written for traditional, long-lived database connections.

Readme

@rodnoycry/ydb-faas

Run YDB inside FaaS handlers (AWS Lambda, Yandex Cloud Functions, Vercel Functions) without giving up libraries that expect a long-lived database connection.

Why this exists

YDB's official guidance for FaaS environments is do not reuse a Driver between invocations. HTTP/2 connections held across frozen process states cause intermittent timeouts and hangs. The driver must be created inside the handler and closed in finally.

That collides with how most database-consuming code is written — initialized once at module scope with a stable connection it can call into for the lifetime of the process. ORMs, query builders, auth libraries (e.g. Better Auth DB adapter): the standard pattern everywhere else assumes one connection lives for the lifetime of one process.

In FaaS with YDB, you have two lifetimes that don't match:

  • Your service / library wants to live for the lifetime of the process (warm-start friendly).
  • The YDB Driver must live for the lifetime of one invocation.

This package bridges them with AsyncLocalStorage: the consumer reads the driver from ambient context per call; the handler creates a fresh driver, binds it to the context, runs the work, and closes the driver when done. Your service code stays written for "normal" lifetimes; the FaaS-specific dance happens once, in your handler.

Install

npm install @rodnoycry/ydb-faas
# peer deps (you almost certainly already have these)
npm install @ydbjs/core @ydbjs/auth @ydbjs/query

Usage

The pattern is two pieces: you pass callback that uses getYdbSql() (for a deferred lookup) to a service, and then call the service methods within runWithYdbSql() (so getYdbSql() can get the driver from the context):

1. Write callback logic using getYdbSql()

import { getYdbSql } from "@rodnoycry/ydb-faas"

async function findUser(id: string) {
    const sql = getYdbSql()
    const [user] = await sql`SELECT * FROM users WHERE id = ${id}`
    return user
}

// Service here - just some third party module
export const service = {
    async handle(event: { userId: string }) {
        return await findUser(event.userId)
    },
}

2. Wrap your handler with runWithYdbSql()

import { Driver } from "@ydbjs/core"
import { EnvironCredentialsProvider } from "@ydbjs/auth/environ"
import { query } from "@ydbjs/query"
import { runWithYdbSql } from "@rodnoycry/ydb-faas"
import { service } from "./service"

export async function handler(event: { userId: string }) {
    const driver = new Driver(process.env.YDB_CONNECTION_STRING!, {
        credentialsProvider: new EnvironCredentialsProvider(),
    })
    // We handle lifetime of driver ourselves using try-finally block
    try {
        await driver.ready()
        return await runWithYdbSql(query(driver), () => service.handle(event))
    } finally {
        await driver.close()
    }
}

getYdbSql() is a deferred lookup, not a captured reference. Each call asks "what's the driver bound to the current async context right now?" and returns whatever's there. At module load nothing is wired up — findUser hasn't decided which driver it'll use, only that it'll use whichever one is current when it actually runs.

The same approach is used in Hono, reference: https://github.com/honojs/hono/blob/main/src/middleware/context-storage/index.ts

Non-FaaS use

If you're on a long-running server (VPS, Cloud Run, Fargate, Yandex Serverless Containers), you don't need this package — the driver lifetime matches the process lifetime, and you can just use query(driver) everywhere without dancing. This bridge is only useful when the driver must be shorter-lived than the code consuming it.

API

runWithYdbSql(sql, fn)

function runWithYdbSql<T>(sql: QueryClient, fn: () => T): T

Binds sql to async-local storage for the duration of fn. Returns whatever fn returns — sync or async, the type flows through. Nested calls shadow the outer binding inside their scope.

getYdbSql()

function getYdbSql(): QueryClient

Returns the QueryClient bound by the enclosing runWithYdbSql(). Throws if called outside of one.

tryGetYdbSql()

function tryGetYdbSql(): QueryClient | undefined

Same as getYdbSql() but returns undefined instead of throwing.

Runtime support

  • Node.js 20.19+ — required for stable AsyncLocalStorage.
  • Edge runtimes — verify node:async_hooks availability.

Examples

  • examples/yandex-cloud-function — a minimal Yandex Cloud Function (TypeScript) wired up end-to-end: handler owns the driver, a separate service module uses getYdbSql() ambiently. Includes local-testing setup (mocked YCF event) and yc CLI deployment steps.

License

MIT