This content originally appeared on DEV Community and was authored by Joel Jaison
This is a submission for the Redis AI Challenge: Beyond the Cache.
What I Built
One request, one intent and KeyPilot knows exactly which API to call.
Imagine you’re juggling five different AI services.
Each has its own API key, its own endpoint, and its own quirks.
Now, every time you want to build something, you have to stop and think:
“Which key should I use? Which service is cheaper for this request? Which one even supports what I need?”
That’s where KeyPilot steps in….
I’ve built a semantic API gateway that listens to what you actually want to do
“Summarize this document” or “Generate an image of a mountain village”
and instantly picks the right API key and endpoint for you.
No hunting through docs. No manual switching.
Here’s the magic:
- Redis Vector Search understands the intent behind your request.
- Redis Caching remembers if we’ve answered this before
- and serves it back in milliseconds without hitting the API again.
- You save time, you save money, and your integration just works faster.
With KeyPilot, I’m not just routing requests,
I’m making API integration faster to build, cheaper to run, and smarter every time you use it.
Demo – Before You Jump In…
I know what you’re thinking…
“Joel, just give me the live link, I’ll click it right now and start playing with it!”
But here’s the thing—without the login credentials, you’ll just end up staring at the login screen wondering what went wrong.
And then… you’ll have to come back here looking for the details anyway.
So let’s save you that awkward extra step, shall we?
Live App – https://smartkeypilot.vercel.app/
Quick Heads-Up
This is a demo app, built fast to show you the core idea. It’s not a locked-down, production grade fortress. Think of it as a cool prototype enough to impress, but not something you’d run your banking on.
A few ground rules:
- No personal API keys, please.
I’ve already included demo-friendly keys for you.
- If you absolutely must use your own, make sure they’re temporary and revocable.
- Demo sessions last 8 minutes. When time’s up, poof all keys are wiped.
- Be nice to the system
—no spam, no abuse, let’s keep the experience smooth for everyone.
Demo Login
Follow this simple pattern:
Username: demo + 1–3 digits → (Example: demo123)
Password: pass + the same digits → (Example: pass123)
Pick any number combo you like just stick to the format. Once you’re in, you’re free to explore with the built in demo API keys.
No setup.
No risk.
Instant fun.
Using the Demo Keys
The app already has demo API keys built in, so you can try out everything semantic intent matching, routing, caching right away.
If you do add your own keys, remember—they’ll vanish as soon as your session expires.
Run It Locally (Optional)
If you landed here before smashing the demo link… I like you already. Nerds unite.
For the best performance, hook it up to Redis Cloud for your connection string this gives you superfast vector search and caching ( fast and simple ).
Frontend repo: https://github.com/Joeljaison391/KeyPilot-Frontend
Backend repo: https://github.com/Joeljaison391/KeyPilot
Short on time?
No problem I’ve got you.
Here’s a quick intro video so you can watch the demo without lifting a finger:
ScreenShots
Welcome to KeyPilot
This is our Landing Page — clean, simple, and inviting.
The goal is to instantly tell you what KeyPilot does and give you a way to dive right in.
Getting Started
Here’s the Login Page no fuss, no confusion.
Just sign in, or hop in using the demo mode to explore without creating an account.
Onboarding in Minutes
New here?
Our Onboarding Tutorial walks you through the essentials, from finding your API keys to using the testing playground so you can get productive right away.
Your Mission Control – The Dashboard
Once inside, the Dashboard is your command center.
See your keys, usage stats, and quick actions all in one place.
Adding a Key
Need a new API key? The Add Key Modal makes it easy.
Choose a provider template, set limits, define allowed origins and you’re done.
Keys are encrypted and automatically expire when they should.
Powered by Redis
Behind the scenes, Redis Cloud powers everything from storing encrypted keys to caching API responses.
Here’s the Redis Cloud dashboard keeping it all running lightning-fast.
Testing APIs in Real-Time
Welcome to the API Testing Playground tweak payloads, change your intent, and watch KeyPilot choose the best template using semantic matching.
Intent Testing (Without Spending Tokens)
Curious which template your request would trigger but don’t want to hit a real API?
The Intent Testing Tool lets you check without making an actual API call.
Smart Caching for Cost & Speed
Why pay for the same API call twice?
KeyPilot uses semantic caching if a similar request was made before, it serves the stored response instantly, saving cost and time.
Monitoring & Insights
Finally, keep track of everything with API Usage Monitoring from tokens used and uptime/downtime, to success rate and cache hits.
How I Used Redis 8
Why Redis? Why Not “Normal” Databases?
Most people think of databases like PostgreSQL, MySQL and MongoDB when building apps.
They’re great for longterm, structured storage, but for this project, I needed something different
Speed over everything – I wanted sub-millisecond lookups.
Built-in expiration – Sessions and API keys should self-destruct after a few minutes, no cron jobs.
Simple, atomic ops – Set it, get it, delete it. No complex joins.
Works as cache and DB – Why juggle two systems when one can do both?
If I had used a normal database:
- I’d have to write extra code to delete expired sessions.
- Every API call would be slower due to disk-based queries.
- Caching would require a separate Redis instance anyway.
So instead of this twosystem headache, I went all in on Redis 8 as a full-fledged primary database for this app.
How Redis Runs the Show in KeyPilot
When I say Redis is the backbone, I mean it literally runs everything from logging you in, to storing your API keys, to making sure your session politely disappears after 8 minutes without me lifting a finger.
Authentication Routes – “You’re In!”
We used Redis Strings & Hashes to store user sessions and encrypted API keys, with TTL auto expiration so they vanish when no longer needed.
This means no manual cleanup, no stale logins, and instant access.
await redis.setEx(`user:${userId}`, 480, JSON.stringify(sessionData));
await redis.expire(`keys:${userId}:${template}`, 480);
API Key Management – “Your Keys, Your Rules”
Every API key got stored in a Redis Hash with metadata like creation time and description.
No duplicate keys, no outdated entries — just clean, encrypted storage.
await redis.hSet(`keys:${userId}:${template}`, {
encrypted_key: encrypted,
description,
created_at: Date.now()
});
Proxy & Semantic Cache – “Smartest Route Wins”
Redis RediSearch + Vector Index let us match the right API key to the right request based on meaning, not just keywords.
Once fetched, the response got cached for blazing replays.
const results = await redis.ft.search(
'idx:intents',
'*=>[KNN 1 @vector $query_vector]',
{ PARAMS: { query_vector } }
);
await redis.setEx(`cache:${userId}:${intentHash}`, 3600, JSON.stringify(apiResponse));
Analytics & RealTime Tracking – “See It As It Happens”
We combined Redis Pub/Sub, Streams, and Counters to track every request in real time.
- Pub/Sub broadcasts “received” and “completed” events to the dashboard instantly.
- Streams keep a time-ordered history of activity and cached requests.
- Counters aggregate daily and weekly stats for quick summaries.
// Live event broadcasts
await redis.publish('channel:request:received', JSON.stringify({ userId, intent, ts: Date.now() }));
await redis.publish('channel:request:completed', JSON.stringify({ userId, latency, cacheHit, ts: Date.now() }));
// Activity stream (last 50 events)
await redis.xAdd(`analytics:activity:${userId}`, '*', { event: 'request:success', intent, latency: String(ms) });
await redis.xTrim(`analytics:activity:${userId}`, 'MAXLEN', 50);
// Daily counters
await redis.incr(`analytics:daily_requests:${userId}:${date}`);
Analytics Dashboard – “Know What’s Trending”
Every intent a user triggered got counted using Sorted Sets.
This gave us instant leaderboards of top requests perfect for spotting patterns.
await redis.zIncrBy(`intent_trends:${userId}:daily`, 1, intent);
const topIntents = await redis.zRange(`intent_trends:${userId}:daily`, -5, -1, { REV: true });
Cache Management – “One Sweep, All Clean”
Redis made it easy to find and wipe old cache keys in bulk.
No messy SQL queries, just a quick scan and delete.
const keys = await redis.scanIterator({ MATCH: `cache:${userId}:*` });
for await (const key of keys) await redis.del(key);
Intent Tracking & Trends – “What Users Want, Right Now”
We kept a running tally of weekly user intents using Sorted Sets.
This helped us predict what users would request next almost like reading minds.
await redis.zIncrBy(`intent_trends:${userId}:weekly`, 1, detectedIntent);
By combining multiple Redis 8 features, we replaced five different systems:
- No extra SQL database for sessions
- No Elasticsearch for search
- No Kafka for event streaming
- No cron jobs for cleanup
- No separate analytics DB
What Tried to Slow Me Down (But Didn’t)
Minimal UI, Maximum Clarity
––––––––––––––––––––––––––––
My rule was simple: if someone needs a manual, I messed up.
So I kept cutting extra text, moving things around at random hours, and swapping long explanations for small icons. I just wanted people to open the app and instantly know what to do.
Time Pressure (Hackathon Mode)
––––––––––––––––––––––––––––
The clock felt louder than my keyboard.
Every decision was the same question: should I make it perfect or just make it work? I went with “make it work.”
Semantic Matching & Provider Templates
––––––––––––––––––––––––––––
The idea was simple: type what you want in plain English, and the app figures out which API to call. Sounds easy… but it wasn’t.
I had to create flexible templates for different services and still keep them accurate. By the time I was done, I’d listened to over 150 songs and sat through 60+ Spotify ads while coding.
Speed Optimization in Practice
––––––––––––––––––––––––––––
Saying “sub-millisecond” is easy. Making it happen? Not so much.
I spent hours tuning Redis queries, cutting down data sizes, and setting up caching all while making sure nothing else broke.
Team
Special thanks to abelboby for contributing to the frontend development and helping bring the user experience to life.
Thank You for Reading
If you made it this far, thank you!
I truly appreciate you taking the time to explore this project and follow along with the journey.
This content originally appeared on DEV Community and was authored by Joel Jaison