Youtube Cache
YouTube video metadata caching with rate limiting, TTL, reservation system, and batch lookups for Convex.
git clone https://github.com/TimpiaAI/convex-youtube-metadata.git
cd convex-youtube-metadataThis 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.
Review the source and its dependencies before adopting this package. Source availability does not establish npm publication or runtime qualification.
Getting started
- Get the source at the revision above and read its package documentation.
- Check the required Bijection SDK version, dependencies, and external service credentials.
- Follow the package setup instructions and the guide to using components.
- 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.
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
- Cache Check -- On every request, the component checks the local Convex database for a cached entry.
- Fresh Hit -- If the entry exists and is within its TTL, it's returned immediately (cache hit).
- Stale/Miss -- If the entry is missing or stale, the component checks the rate limiter.
- Quota Available -- If quota is available, it fetches fresh data from the YouTube API.
- Quota Exhausted -- If quota is exhausted, a reservation is created. The request waits (up to
reservationTimeoutMs) for quota to free up. - Graceful Degradation -- If the wait times out, stale data is returned when available. Otherwise, null is returned.
- Retry Logic -- Transient HTTP errors trigger exponential backoff retries (up to
maxRetriesattempts).
API Reference
YouTubeMetadataCache class
| Method | Context | Description |
|---|---|---|
getVideo(ctx, { videoId, ttl? }) | action | Get metadata for a single video |
getVideos(ctx, { videoIds, ttl? }) | action | Batch lookup for multiple videos |
getCacheStats(ctx) | query | Get hit rate, quota usage, reservations |
clearCache(ctx) | mutation | Clear all cached entries and reset stats |
setQuotaLimit(ctx, { quotaLimit }) | mutation | Update the daily quota limit |
cleanupStale(ctx) | mutation | Remove entries past their TTL |
resetQuota(ctx) | mutation | Reset quota counter and start fresh window |
VideoMetadata type
| Field | Type | Description |
|---|---|---|
videoId | string | YouTube video ID |
title | string | Video title |
description | string | Video description |
thumbnailUrl | string | Highest quality thumbnail URL |
duration | string | ISO 8601 duration (e.g. PT4M13S) |
channelId | string | Channel ID |
channelTitle | string | Channel name |
publishedAt | string | ISO 8601 publish date |
viewCount | string | View count |
likeCount | string | Like count |
cachedAt | number | When this entry was cached (ms since epoch) |
ttl | number | TTL in milliseconds |
fresh | boolean | Whether the entry is within its TTL |
Constructor options
| Option | Type | Default | Description |
|---|---|---|---|
apiKey | string | required | YouTube Data API v3 key |
defaultTtlMs | number | 3,600,000 | Default cache TTL (1 hour) |
quotaLimit | number | 10,000 | Max quota units per day |
reservationTimeoutMs | number | 10,000 | Max wait time for quota (10s) |
maxRetries | number | 3 | Retry attempts on transient failures |
baseRetryDelayMs | number | 1,000 | Base delay for exponential backoff |
Live Demo
Check out the live demo at youtube-metadata-demo.vercel.app.
Author
Built and maintained by TimpiaAI.