Backend service for event collection, API key management, reporting, short URL tracking, and analytics aggregation. This project is designed to be scalable, cache-optimized, and deployable on modern cloud providers.
Live Deployment URL (Render): https://alter-office-w7nh.onrender.com
API Documentation (Swagger/OpenAPI): https://alter-office-w7nh.onrender.com/docs
This backend provides a complete analytics system designed to be integrated into any website or mobile application. It supports high-volume event ingestion, efficient reporting, API key management, short URL tracking, and device/user-based insights.
The system follows a modular, scalable architecture and uses PostgreSQL, Redis caching, and Fastify for high-performance handling.
All requirements from the task brief have been implemented and validated.
- Register application and generate API key
- API key hashing and TTL support
- Key revocation and regeneration
- API key validation middleware
- Authentication via
x-api-keyheader
- High-volume event ingestion
- Records URL, referrer, userId, device, metadata, IP, timestamp
- Automatic timestamp fallback
- Optimized PostgreSQL schema
- Event summary with device-level breakdown
- Unique user counts (IP-based)
- User-level statistics (recent event, device info, total events)
- Supports date filters
- Supports app-level and cross-app queries
- Implemented using
@fastify/rate-limit - Applied specifically to ingestion endpoints
- Create short URLs
- Redirect handler
- Auto-record analytics event
shorturl_clickon redirection
- Event summaries
- User statistics
- API key validation
- Automatic TTL-based caching
- Jest-based tests
- Supertest integration testing
- Test server builder to avoid port conflicts
- Covers Auth, Analytics, Short URL modules
- Complete OpenAPI 3.0 documentation
- Includes schemas, tags, and security handling
- Fully deployed on Render
- Production build
- Environment-variable-driven configuration
- Works without Docker (optional)
| Component | Technology |
|---|---|
| Backend Framework | Fastify (Node.js) |
| Database | PostgreSQL |
| Cache | Redis |
| ORM | Prisma |
| Testing | Jest + Supertest |
| Documentation | Swagger / OpenAPI |
| ID Generation | nanoid |
| Deployment | Render |
src/
modules/
auth/
auth.controller.ts
auth.routes.ts
auth.service.ts
apiKey.middleware.ts
analytics/
analytics.controller.ts
analytics.routes.ts
analytics.service.ts
shorturl/
shorturl.routes.ts
shorturl.service.ts
utils/
prisma.ts
redis.ts
crypto.util.ts
server.ts
buildServer.ts
tests/
auth.test.ts
analytics.test.ts
shorturl.test.ts
prisma/
schema.prisma
scripts/
debugging scripts
npm installnpx prisma generatenpm run devnpm run build
npm startnpx jest --runInBandPORT=4000
NODE_ENV=production
CORS_ORIGIN=*
DATABASE_URL="postgresql://<user>:<password>@<host>:<port>/<db>?sslmode=require"
REDIS_HOST=<host>
REDIS_PORT=<port>
REDIS_PASSWORD=<password>
API_KEY_TTL_DAYS=365
API_KEY_BYTE_SIZE=32
RATE_LIMIT_REQUESTS=500
RATE_LIMIT_WINDOW=60
JWT_SECRET=supersecret123
GOOGLE_CLIENT_ID=dummy
GOOGLE_CLIENT_SECRET=dummy
GOOGLE_REDIRECT_URI=https://localhost/auth/callback
SWAGGER_ENABLED=true
PRISMA_CLIENT_ENGINE_TYPE=binary
BASE_URL=https://alter-office-w7nh.onrender.com
POST /api/auth/register
Registers a new client application.
Request:
{
"name": "MyApp",
"ownerEmail": "admin@example.com"
}Response:
{
"apiKey": "...",
"appId": "..."
}POST /api/auth/revoke
{
"appId": "..."
}POST /api/auth/regenerate
{
"appId": "..."
}POST /api/analytics/collect
Headers:
x-api-key: <key>
Body:
{
"event": "button_click",
"url": "https://example.com",
"referrer": "https://google.com",
"device": "mobile",
"userId": "user123",
"metadata": {
"browser": "Chrome",
"os": "Windows"
}
}GET /api/analytics/event-summary
Example:
/api/analytics/event-summary?event=button_click&startDate=2024-01-01&endDate=2024-01-15
GET /api/analytics/user-stats?userId=user123
POST /api/shorten
{
"originalUrl": "https://example.com/very-long-url"
}Response:
{
"shortId": "abc123",
"shortUrl": "https://alter-office-w7nh.onrender.com/r/abc123"
}GET /r/:shortId
Redirects and logs click event.
model App {
id String @id @default(uuid())
name String
ownerEmail String
apiKeyHash String
expiresAt DateTime?
revoked Boolean @default(false)
createdAt DateTime @default(now())
events Event[] @relation("AppEvents")
}
model Event {
id BigInt @id @default(autoincrement())
appId String
app App @relation("AppEvents", fields: [appId], references: [id])
eventName String
url String?
referrer String?
device String?
ipAddress String?
userId String?
timestamp DateTime @default(now())
metadata Json?
}
model ShortUrl {
id String @id
appId String
originalUrl String
createdAt DateTime @default(now())
}- Fastify chosen for performance and plugin ecosystem
- Prisma ORM with binary engine for cloud deployment
- Redis caching layer to reduce DB load
- Modular design for extendability and maintainability
- Short URL module added as an additional analytics feature
- Tests built using ephemeral Fastify injection server
- Fastify preParsing Hook Error: Resolved by removing unnecessary global hooks.
- Prisma table mismatch: Short URL table added manually; raw SQL used for compatibility.
- Render build errors: Resolved by adding
@types/nodeto production dependencies. - Tests timing out: BuildServer separation resolved listener issues.
- Dashboard UI
- Queue-based ingestion (BullMQ)
- Advanced user-agent parsing
- App-level team management
- Admin portal
This project meets all requirements specified in the task brief:
- API key management
- Event collection
- Analytics aggregation
- Rate limiting
- Short URL module
- Caching system
- Deployment
- Testing coverage
- Clean documentation
The backend is scalable, production-ready, and cloud-deployed.