{"id":51403744,"url":"https://github.com/anurag77889/pulseboard","last_synced_at":"2026-07-04T09:30:35.550Z","repository":{"id":364267873,"uuid":"1266978899","full_name":"anurag77889/pulseboard","owner":"anurag77889","description":"FastAPI using Redis for Social Feeds","archived":false,"fork":false,"pushed_at":"2026-06-29T15:53:52.000Z","size":10687,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-29T16:26:53.016Z","etag":null,"topics":["fastapi","instagram","redis","redis-cache","social"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/anurag77889.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-12T05:48:38.000Z","updated_at":"2026-06-29T15:54:19.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/anurag77889/pulseboard","commit_stats":null,"previous_names":["anurag77889/pulseboard"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/anurag77889/pulseboard","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anurag77889%2Fpulseboard","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anurag77889%2Fpulseboard/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anurag77889%2Fpulseboard/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anurag77889%2Fpulseboard/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/anurag77889","download_url":"https://codeload.github.com/anurag77889/pulseboard/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anurag77889%2Fpulseboard/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35117334,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-04T02:00:05.987Z","response_time":113,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fastapi","instagram","redis","redis-cache","social"],"created_at":"2026-07-04T09:30:35.062Z","updated_at":"2026-07-04T09:30:35.544Z","avatar_url":"https://github.com/anurag77889.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PulseBoard 🔴\n\nA small FastAPI backend built to learn **Redis end-to-end** — not just \"what is Redis,\" but how each of its core data structures solves a real production problem.\n\nNo fluff, no over-engineering. Six features, six Redis data types, all wired into one working API.\n\n---\n\n## Why this project exists\n\nMost Redis tutorials show you `SET` and `GET` and call it a day. That's maybe 10% of what Redis is actually used for in production.\n\nPulseBoard simulates a small social platform — and every feature was picked because it's a textbook real-world use case for a specific Redis data structure:\n\n| Feature | Redis Data Structure | What it teaches |\n|---|---|---|\n| User profile caching | **String** | Cache-aside pattern, TTL, invalidation |\n| Activity feed | **List** | Ordered, bounded, append-heavy data |\n| Leaderboard | **Sorted Set** | Atomic ranking, score-based queries |\n| Login sessions | **Hash** | Structured objects, partial field updates |\n| Online presence \u0026 social graph | **Set** | Membership checks, intersection/difference |\n| API rate limiting \u0026 live notifications | **String + Pub/Sub** | Atomic counters, real-time broadcasting |\n\nBy the time you've played with all six, you'll understand *why* Redis is used the way it is in real backends — not just the commands.\n\n---\n\n## What you'll need\n\n- Python 3.10+\n- Redis running locally (instructions below)\n- `curl` or Postman/Swagger UI for testing\n- ~30–60 minutes if you want to walk through every feature\n\nNo Docker, no cloud account, no signup. Everything runs on your machine.\n\n---\n\n## Quick start\n\n### 1. Get Redis running\n\n**macOS:**\n```bash\nbrew install redis\nbrew services start redis\n```\n\n**Ubuntu / Debian:**\n```bash\nsudo apt update \u0026\u0026 sudo apt install redis-server\nsudo systemctl start redis-server\n```\n\n**Windows:** use [WSL](https://learn.microsoft.com/en-us/windows/wsl/install) and follow the Ubuntu steps above, or run Redis via Docker:\n```bash\ndocker run -d -p 6379:6379 redis:latest\n```\n\n**Verify it's running:**\n```bash\nredis-cli ping\n```\nYou should see `PONG`. If you don't, Redis isn't running — check the steps above before continuing.\n\n### 2. Clone and set up the project\n\n```bash\ngit clone https://github.com/anurag77889/pulseboard.git\ncd pulseboard\n\npython3 -m venv venv\nsource venv/bin/activate        # Windows: venv\\Scripts\\activate\n\npip install -r requirements.txt\n```\n\n### 3. Run it\n\n```bash\nuvicorn main:app --reload\n```\n\nThe API is now live at **http://localhost:8000**.\n\nOpen **http://localhost:8000/docs** — that's FastAPI's built-in Swagger UI. You can try every single endpoint from your browser without writing any `curl` commands. This is the easiest way to explore the project.\n\n---\n\n## Project structure\n\n```\npulseboard/\n├── main.py                 # App entry point — wires everything together\n├── redis_client.py         # Single shared Redis connection\n├── fake_db.py               # In-memory \"database\" (no real DB needed)\n├── requirements.txt\n└── routers/\n    ├── cache.py             # Feature 1 — Strings\n    ├── feed.py               # Feature 2 — Lists\n    ├── leaderboard.py        # Feature 3 — Sorted Sets\n    ├── sessions.py            # Feature 4 — Hashes\n    ├── presence.py            # Feature 5 — Sets\n    ├── rate_limiter.py        # Feature 6a — Strings (rate limiting)\n    └── notifications.py       # Feature 6b — Pub/Sub\n```\n\nEach file in `routers/` is self-contained — one feature, one Redis data structure, one thing to understand at a time. There's no real database; `fake_db.py` is a plain Python dict standing in for one, so 100% of the focus stays on Redis.\n\n---\n\n## Walkthrough — try every feature\n\nEach section below is copy-paste runnable. Open a terminal and go in order, or jump to whichever feature interests you most.\n\n### 1. Caching (Strings)\n\n```bash\n# First call — slow, hits the \"database\"\ncurl http://localhost:8000/users/u1\n\n# Second call — instant, served from Redis cache\ncurl http://localhost:8000/users/u1\n\n# Peek at the cache directly\ncurl http://localhost:8000/cache/inspect/u1\n```\nLook for `\"source\": \"db\"` on the first call and `\"source\": \"cache\"` on the second.\n\n---\n\n### 2. Activity feed (Lists)\n\n```bash\n# Record some actions\ncurl -X POST http://localhost:8000/users/u1/actions \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"action_type\": \"liked_post\", \"target_id\": \"post_42\"}'\n\n# Read the feed back — most recent first\ncurl http://localhost:8000/users/u1/feed\n```\n\n---\n\n### 3. Leaderboard (Sorted Sets)\n\n```bash\n# See the top 5 right now\ncurl http://localhost:8000/leaderboard\n\n# Give someone points and watch their rank update\ncurl -X POST \"http://localhost:8000/leaderboard/Rohan/add-points?points=500\"\n\ncurl http://localhost:8000/leaderboard\n```\n\n---\n\n### 4. Login sessions (Hashes)\n\n```bash\n# Log in — get a session token back\ncurl -X POST http://localhost:8000/auth/login \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"username\": \"Anurag\", \"password\": \"password123\"}'\n\n# Copy the token from the response, then:\nexport TOKEN=\"paste_token_here\"\n\ncurl \"http://localhost:8000/auth/session?token=$TOKEN\"\n```\n\n---\n\n### 5. Presence \u0026 social graph (Sets)\n\n```bash\ncurl -X POST http://localhost:8000/presence/Anurag/online\ncurl -X POST http://localhost:8000/presence/Priya/online\n\ncurl http://localhost:8000/presence/online/all\n\n# Who do Anurag and Priya both follow?\ncurl http://localhost:8000/users/Anurag/mutuals/Priya\n```\n\n---\n\n### 6a. Rate limiting (Strings + atomic counters)\n\n```bash\n# Hit this 6 times fast — the 6th request gets blocked\nfor i in 1 2 3 4 5 6; do\n  curl -s \"http://localhost:8000/api/protected-resource?username=Anurag\"\n  echo \"\"\ndone\n```\n\n---\n\n### 6b. Live notifications (Pub/Sub)\n\nThis one needs **two terminals**, since you need a listener and a sender running at the same time.\n\n**Terminal A** — connect a listener (requires [`websocat`](https://github.com/vi/websocat), or use a browser console):\n```bash\nwebsocat ws://localhost:8000/ws/notifications/Anurag\n```\n\n**Terminal B** — send a notification while Terminal A is still open:\n```bash\ncurl -X POST http://localhost:8000/users/Anurag/notify \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"message\": \"Priya liked your post\"}'\n```\n\nThe message should appear instantly in Terminal A.\n\n---\n\n## See what Redis is actually doing\n\nThis is the most underrated way to build real intuition. Open `redis-cli` in a separate terminal:\n\n```bash\nredis-cli\n\n\u003e KEYS *                    # every key currently in Redis\n\u003e TYPE user:u1               # see the data type behind any key\n\u003e MONITOR                    # streams every command Redis receives, live\n```\n\nRun `MONITOR`, then hit a few endpoints from another terminal or from `/docs`. You'll watch the exact Redis commands fire in real time — it's the fastest way to connect \"I called this API\" to \"this is what happened in Redis.\"\n\n---\n\n## Common issues\n\n**`redis.exceptions.ConnectionError`**\nRedis isn't running. Run `redis-cli ping` — if it doesn't return `PONG`, start Redis using the steps in Quick Start.\n\n**Port 8000 already in use**\nRun on a different port: `uvicorn main:app --reload --port 8001`\n\n**WebSocket notification not arriving**\nPub/Sub is fire-and-forget — the subscriber (Terminal A) must already be connected *before* you publish. If you publish first, the message is lost; there's nothing to replay it. This is intentional and a good thing to notice — it's a real limitation of Redis Pub/Sub.\n\n---\n\n## What's intentionally left out\n\nThis project skips a few things on purpose, to keep the focus on core Redis mechanics:\n\n- **No real database** — `fake_db.py` is a Python dict. Adding Postgres would split focus away from Redis.\n- **No authentication hardening** — passwords are stored in plaintext in `fake_db.py` for simplicity. Don't reuse this auth pattern anywhere real.\n- **No Redis Cluster / persistence config** — this runs against a single local Redis instance with defaults. Production Redis setups (replication, RDB/AOF persistence, Sentinel/Cluster) are a separate, deeper topic.\n\nIf you want to go further after this, natural next steps are: connection pooling, Redis Streams (durable Pub/Sub), and Redis Cluster for horizontal scaling.\n\n---\n\n## License\n\nMIT — use this however you like, for learning or for forking into your own project.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanurag77889%2Fpulseboard","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanurag77889%2Fpulseboard","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanurag77889%2Fpulseboard/lists"}