Skip to content

Find a component

Loading the directory…

↑ ↓ to select · Enter to open · Esc to closeBrowse all →
Contributor login

Youtube Cache

YouTube video metadata caching with rate limiting, TTL, reservation system, and batch lookups for Convex.

Upstream source
git clone https://github.com/TimpiaAI/convex-youtube-metadata.git
cd convex-youtube-metadata

This upstream package has not been adapted or qualified for Bijection. Read the original documentation before adopting it.

Description

YouTube video metadata caching with rate limiting, TTL, reservation system, and batch lookups for Convex.

Explore the package README for API concepts, configuration, and examples. Check the Bijection source for adaptation-specific setup.

Available to evaluate

Review the source and its dependencies before adopting this package. Source availability does not establish npm publication or runtime qualification.

Getting started

  1. Get the source at the revision above and read its package documentation.
  2. Check the required Bijection SDK version, dependencies, and external service credentials.
  3. Follow the package setup instructions and the guide to using components.
  4. Exercise the component in your deployment according to your project’s verification rules.

Open source

Maintained source: TimpiaAI/convex-youtube-metadata. License: See repository. Consult the repository for license terms, notices, and contributor attribution.

From the upstream publisher

Convex component for YouTube video metadata caching with built-in rate limiting, TTL, reservation system, and batch lookups

Explore the demo ↗

Upstream overview

From the upstream package documentation.

This component provides a smart caching layer for YouTube video metadata with built-in rate limiting and quota management. It implements stale-while-revalidate patterns to return cached data immediately while fetching fresh data in the background. The component includes a reservation system that queues requests when quota is exhausted and supports batch lookups to optimize API usage against YouTube's daily limits.

Use cases

From the upstream package documentation.

  • Build video platforms or course sites that need to display YouTube metadata without hitting API limits on every page load
  • Cache video information for playlists or video collections where the same videos are accessed frequently by multiple users
  • Implement video search or recommendation features that need fast metadata access with graceful degradation when quotas are exhausted
  • Create content management systems that aggregate YouTube videos and need reliable metadata even during high traffic periods
  • Build analytics dashboards that track YouTube video performance without burning through API quotas on repeated queries

How it works

From the upstream package documentation.

The component registers as a Convex component through defineApp() and exposes a YouTubeMetadataCache class that wraps the YouTube Data API v3. When you call getVideo() or getVideos(), it first checks the Convex database for cached entries within their TTL period.

If data is stale or missing, the component checks its rate limiter before making YouTube API calls. When quota is available, it fetches fresh data and updates the cache. If quota is exhausted, it creates a reservation and waits up to the configured timeout for quota to free up, returning stale data as a fallback.

The component tracks quota usage, cache hit rates, and active reservations through getCacheStats(). You can manage the cache lifecycle with methods like clearCache(), cleanupStale(), and setQuotaLimit() to handle different operational scenarios. Batch operations use YouTube's ability to fetch up to 50 videos per API call to minimize quota consumption.

Upstream package FAQ

How does convex-youtube-cache prevent API quota exhaustion?

The convex-youtube-cache component includes built-in rate limiting with configurable daily quotas (default 10,000 units per day). When quota is exhausted, it creates reservations that queue requests and wait up to a configurable timeout (default 10 seconds) before gracefully degrading to return stale cached data or null.

Can I fetch multiple YouTube videos efficiently with this component?

Yes, the convex-youtube-cache component provides a getVideos method that supports batch lookups for up to 50 video IDs in a single YouTube API call. This significantly reduces quota usage compared to individual requests and includes the same caching and rate limiting features.

What happens when cached YouTube data becomes stale?

The convex-youtube-cache component implements a stale-while-revalidate strategy. When cached data exceeds its TTL, it returns the stale data immediately for fast response times, then fetches fresh data from the YouTube API in the background if quota is available.

How do I monitor YouTube API usage with this component?

The convex-youtube-cache component provides a getCacheStats method that returns hit rate, quota usage, and active reservations. You can call this from a Convex query to monitor performance and track how efficiently your app is using the YouTube API quota.

Does convex-youtube-cache handle YouTube API errors and retries?

Yes, the convex-youtube-cache component includes retry logic with exponential backoff for transient HTTP errors. It supports configurable retry attempts (default 3) and base retry delays (default 1 second) to handle temporary YouTube API failures gracefully.

Use with agents and CLI

Give your coding agent the component’s source identity and setup guidance.

agent-prompt.md
Help me integrate Youtube Cache with Bijection.

Read: https://bijection.com/components/convex-youtube-cache/SKILL.md

Check SDK compatibility and dependency availability.
Follow this project's execution and verification rules.

Upstream README.md

View repository ↗

Documentation from TimpiaAI/convex-youtube-metadata, recorded October 23, 2026. APIs and setup may differ in the Bijection adaptation.

convex-youtube-metadata

A Convex component for YouTube video metadata caching with built-in rate limiting, TTL management, a reservation system, and batch lookups.

Built for apps that need fast, reliable access to YouTube video data without exceeding API quotas.

Convex Components Challenge -- YouTube Metadata Cache with Rate Limiting

Features

  • Smart Caching -- Cache video metadata (title, description, thumbnail, duration, channel info) with configurable TTL
  • Rate Limiting -- Built-in rate limiter to stay within YouTube API quotas (default: 10,000 units/day)
  • Reservation System -- Queue requests when at capacity, wait up to configurable timeout (default 10s) before failing
  • Stale-While-Revalidate -- Return cached data immediately when available, fetch fresh data when stale or missing
  • Batch Lookups -- Fetch multiple video IDs in a single API call for efficient quota usage
  • Cache Statistics -- Monitor hit rate, quota usage, and active reservations
  • Retry with Backoff -- Configurable retry logic with exponential backoff on transient failures
  • Zero Environment Variables -- YouTube API key passed as configuration (components cannot use env vars)

Installation

npm install convex-youtube-metadata

Setup

1. Register the component

// convex/convex.config.ts
import { defineApp } from "convex/server";
import youtubeMetadata from "convex-youtube-metadata/convex.config";

const app = defineApp();
app.use(youtubeMetadata);

export default app;

2. Initialize the client

// convex/youtube.ts
import { YouTubeMetadataCache } from "convex-youtube-metadata";
import { components } from "./_generated/api.js";

const ytCache = new YouTubeMetadataCache(components.youtubeMetadata, {
  apiKey: "YOUR_YOUTUBE_DATA_API_V3_KEY",
  defaultTtlMs: 3_600_000, // 1 hour (optional)
  quotaLimit: 10_000,       // daily quota (optional)
  reservationTimeoutMs: 10_000, // 10s wait (optional)
  maxRetries: 3,            // retry attempts (optional)
  baseRetryDelayMs: 1_000,  // backoff base (optional)
});

Tip: Store your YouTube API key in the Convex dashboard as an environment variable, then pass it to the constructor:

const ytCache = new YouTubeMetadataCache(components.youtubeMetadata, {
  apiKey: process.env.YOUTUBE_API_KEY!,
});

Usage

Get a single video

import { action } from "./_generated/server.js";
import { v } from "convex/values";

export const getVideo = action({
  args: { videoId: v.string() },
  handler: async (ctx, args) => {
    const video = await ytCache.getVideo(ctx, {
      videoId: args.videoId,
    });

    if (!video) throw new Error("Video not found");

    return {
      title: video.title,
      channel: video.channelTitle,
      duration: video.duration,
      views: video.viewCount,
    };
  },
});

Batch lookup

export const getPlaylist = action({
  args: { videoIds: v.array(v.string()) },
  handler: async (ctx, args) => {
    // Single API call for up to 50 videos
    const videos = await ytCache.getVideos(ctx, {
      videoIds: args.videoIds,
      ttl: 2 * 60 * 60 * 1000, // 2 hour TTL
    });

    return videos.filter((v) => v !== null);
  },
});

Check cache stats

import { query } from "./_generated/server.js";

export const stats = query({
  handler: async (ctx) => {
    const stats = await ytCache.getCacheStats(ctx);

    return {
      hitRate: `${(stats.hitRate * 100).toFixed(1)}%`,
      quotaUsed: `${stats.quotaUsed}/${stats.quotaLimit}`,
      activeReservations: stats.activeReservations,
    };
  },
});

Clear cache

import { mutation } from "./_generated/server.js";

export const resetCache = mutation({
  handler: async (ctx) => {
    const deleted = await ytCache.clearCache(ctx);
    console.log(`Cleared ${deleted} cached videos`);
  },
});

Adjust quota limit

export const updateQuota = mutation({
  handler: async (ctx) => {
    // If you have a higher quota from Google
    await ytCache.setQuotaLimit(ctx, { quotaLimit: 50_000 });
  },
});

Schedule stale cleanup

// convex/crons.ts
import { cronJobs } from "convex/server";
import { internal } from "./_generated/api.js";

const crons = cronJobs();
crons.hourly("cleanup stale cache", { minuteUTC: 0 }, internal.youtube.cleanup);
export default crons;

// convex/youtube.ts
export const cleanup = internalMutation({
  handler: async (ctx) => {
    const deleted = await ytCache.cleanupStale(ctx);
    console.log(`Cleaned up ${deleted} stale entries`);
  },
});

How It Works

  1. Cache Check -- On every request, the component checks the local Convex database for a cached entry.
  2. Fresh Hit -- If the entry exists and is within its TTL, it's returned immediately (cache hit).
  3. Stale/Miss -- If the entry is missing or stale, the component checks the rate limiter.
  4. Quota Available -- If quota is available, it fetches fresh data from the YouTube API.
  5. Quota Exhausted -- If quota is exhausted, a reservation is created. The request waits (up to reservationTimeoutMs) for quota to free up.
  6. Graceful Degradation -- If the wait times out, stale data is returned when available. Otherwise, null is returned.
  7. Retry Logic -- Transient HTTP errors trigger exponential backoff retries (up to maxRetries attempts).

API Reference

YouTubeMetadataCache class

MethodContextDescription
getVideo(ctx, { videoId, ttl? })actionGet metadata for a single video
getVideos(ctx, { videoIds, ttl? })actionBatch lookup for multiple videos
getCacheStats(ctx)queryGet hit rate, quota usage, reservations
clearCache(ctx)mutationClear all cached entries and reset stats
setQuotaLimit(ctx, { quotaLimit })mutationUpdate the daily quota limit
cleanupStale(ctx)mutationRemove entries past their TTL
resetQuota(ctx)mutationReset quota counter and start fresh window

VideoMetadata type

FieldTypeDescription
videoIdstringYouTube video ID
titlestringVideo title
descriptionstringVideo description
thumbnailUrlstringHighest quality thumbnail URL
durationstringISO 8601 duration (e.g. PT4M13S)
channelIdstringChannel ID
channelTitlestringChannel name
publishedAtstringISO 8601 publish date
viewCountstringView count
likeCountstringLike count
cachedAtnumberWhen this entry was cached (ms since epoch)
ttlnumberTTL in milliseconds
freshbooleanWhether the entry is within its TTL

Constructor options

OptionTypeDefaultDescription
apiKeystringrequiredYouTube Data API v3 key
defaultTtlMsnumber3,600,000Default cache TTL (1 hour)
quotaLimitnumber10,000Max quota units per day
reservationTimeoutMsnumber10,000Max wait time for quota (10s)
maxRetriesnumber3Retry attempts on transient failures
baseRetryDelayMsnumber1,000Base delay for exponential backoff

Live Demo

Check out the live demo at youtube-metadata-demo.vercel.app.

Author

Built and maintained by TimpiaAI.

License

MIT

Keywords