Learn how to add a user-to-user recommendation system to your web app for personalized, engaging user experiences.

Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
Why User-to-User Recommendations Matter
User-to-user recommendation systems have transformed how we connect online. Think about how LinkedIn suggests "People You May Know" or how Spotify's "Fans Also Like" feature works. These systems create network effects that can dramatically increase engagement and retention in your application.
Three Core Approaches
Let's explore how to implement each approach in a practical, maintainable way.
How It Works
Collaborative filtering analyzes user behaviors (likes, clicks, views) to identify patterns between users. If User A and User B both interact with similar content, they might be interested in connecting.
Implementation Steps
Here's a simplified Python implementation using a popular library:
import pandas as pd
from scipy.sparse import csr_matrix
from sklearn.neighbors import NearestNeighbors
# Sample interaction data: user_id, item_id, interaction_strength
interactions = [
[1, 101, 5], [1, 102, 3], [2, 101, 4], [2, 103, 5], [3, 102, 4], [3, 104, 5]
]
df = pd.DataFrame(interactions, columns=['user_id', 'item_id', 'strength'])
# Create a user-item matrix
user_item_matrix = df.pivot(index='user_id', columns='item_id', values='strength').fillna(0)
# Convert to sparse matrix for efficiency
sparse_matrix = csr_matrix(user_item_matrix.values)
# Create model (using cosine similarity)
model = NearestNeighbors(metric='cosine', algorithm='brute')
model.fit(sparse_matrix)
# Find similar users for user_id=1
distances, indices = model.kneighbors(user_item_matrix.iloc[0, :].values.reshape(1, -1), n_neighbors=3)
# Get recommended users (excluding the user themselves)
similar_users = user_item_matrix.index[indices.flatten()][1:]
print(f"Recommended users for user 1: {similar_users.tolist()}")
Database Schema
You'll need to track user interactions. Here's a simple SQL schema:
CREATE TABLE user_interactions (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL,
item_id BIGINT NOT NULL, -- could be content_id, product_id, etc.
interaction_type VARCHAR(50) NOT NULL, -- e.g., 'view', 'like', 'comment'
strength FLOAT NOT NULL, -- normalized interaction strength
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX (user_id),
INDEX (item_id)
);
How It Works
Content-based filtering looks at user profiles and attributes rather than behaviors. If User A and User B have similar job titles, interests, or demographic information, they might be good connections.
Implementation Steps
Here's how you might implement this:
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
# Sample user profiles
users = [
{'user_id': 1, 'interests': 'programming python javascript', 'location': 'New York', 'role': 'developer'},
{'user_id': 2, 'interests': 'javascript react frontend', 'location': 'Boston', 'role': 'developer'},
{'user_id': 3, 'interests': 'marketing social media', 'location': 'Chicago', 'role': 'marketer'},
{'user_id': 4, 'interests': 'python machine learning AI', 'location': 'Seattle', 'role': 'data scientist'}
]
df = pd.DataFrame(users)
# Combine text features
df['profile_features'] = df['interests'] + ' ' + df['location'] + ' ' + df['role']
# Convert text to vectors using TF-IDF
vectorizer = TfidfVectorizer(stop_words='english')
tfidf_matrix = vectorizer.fit_transform(df['profile_features'])
# Calculate cosine similarity between users
cosine_sim = cosine_similarity(tfidf_matrix, tfidf_matrix)
# Function to get recommendations for a user
def get_recommendations(user_id, cosine_sim=cosine_sim):
# Get user index
idx = df[df['user_id'] == user_id].index[0]
# Get similarity scores
sim_scores = list(enumerate(cosine_sim[idx]))
# Sort users by similarity score
sim_scores = sorted(sim_scores, key=lambda x: x[1], reverse=True)
# Get top 3 similar users (excluding self)
sim_scores = sim_scores[1:4]
# Get user indices
user_indices = [i[0] for i in sim_scores]
# Return user IDs and similarity scores
return [(df['user_id'].iloc[i], sim_scores[idx][1]) for idx, i in enumerate(user_indices)]
# Get recommendations for user 1
recommendations = get_recommendations(1)
print(f"Recommended users for user 1: {recommendations}")
Schema Extensions
To support content-based filtering, ensure your user profiles contain rich information:
CREATE TABLE user_profiles (
user_id BIGINT PRIMARY KEY,
bio TEXT,
interests TEXT,
skills TEXT,
location VARCHAR(100),
industry VARCHAR(100),
role VARCHAR(100),
-- Additional fields relevant to your application
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FULLTEXT INDEX (bio, interests, skills)
);
How It Works
Graph-based recommendations leverage network theory to find potential connections. The classic "friend of a friend" recommendation is a simple graph algorithm.
Implementation Steps
Here's a simplified implementation using NetworkX:
import networkx as nx
import matplotlib.pyplot as plt
# Create a graph
G = nx.Graph()
# Add users as nodes
users = [1, 2, 3, 4, 5, 6, 7, 8]
G.add_nodes_from(users)
# Add existing connections as edges
connections = [(1, 2), (1, 3), (2, 3), (2, 4), (3, 5), (4, 6), (5, 7), (6, 8)]
G.add_edges_from(connections)
# Function to get friend-of-friend recommendations
def get_friend_recommendations(G, user_id):
# Get direct friends
friends = list(G.neighbors(user_id))
# Collect friend-of-friends
fof = {}
for friend in friends:
for friend_of_friend in G.neighbors(friend):
# Skip if already a friend or the user themselves
if friend_of_friend != user_id and friend_of_friend not in friends:
if friend_of_friend in fof:
fof[friend_of_friend] += 1 # Increment common connection count
else:
fof[friend_of_friend] = 1
# Sort by number of common connections
recommendations = sorted(fof.items(), key=lambda x: x[1], reverse=True)
return recommendations
# Get recommendations for user 1
recommendations = get_friend_recommendations(G, 1)
print(f"Recommended users for user 1: {recommendations}")
# Visualize the graph (optional)
nx.draw(G, with_labels=True, node_color='lightblue', node_size=500, font_weight='bold')
plt.title("User Connection Graph")
plt.show()
Database Schema for Graph Relationships
For small to medium applications, a relational database can handle graph relationships:
CREATE TABLE user_connections (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL,
connected_user_id BIGINT NOT NULL,
connection_type VARCHAR(50) NOT NULL, -- e.g., 'friend', 'follow', 'colleague'
strength FLOAT DEFAULT 1.0, -- optional: connection strength
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY (user_id, connected_user_id),
INDEX (user_id),
INDEX (connected_user_id)
);
For larger applications, consider a dedicated graph database like Neo4j.
Backend Implementation
Here's a simplified Node.js Express API endpoint:
const express = require('express');
const redis = require('redis');
const { promisify } = require('util');
const router = express.Router();
// Redis client for caching
const redisClient = redis.createClient(process.env.REDIS_URL);
const getAsync = promisify(redisClient.get).bind(redisClient);
const setAsync = promisify(redisClient.set).bind(redisClient);
// Get user recommendations
router.get('/api/users/:userId/recommendations', async (req, res) => {
try {
const { userId } = req.params;
const cacheKey = `user_recommendations:${userId}`;
// Try to get from cache first
const cachedRecommendations = await getAsync(cacheKey);
if (cachedRecommendations) {
return res.json(JSON.parse(cachedRecommendations));
}
// If not in cache, compute recommendations
// This could call your Python recommendation engine via API
const recommendations = await computeRecommendations(userId);
// Store in cache for 24 hours
await setAsync(cacheKey, JSON.stringify(recommendations), 'EX', 86400);
return res.json(recommendations);
} catch (error) {
console.error('Error fetching recommendations:', error);
return res.status(500).json({ error: 'Failed to fetch recommendations' });
}
});
// Mock function - in production, this would call your ML service
async function computeRecommendations(userId) {
// This could make an HTTP request to your recommendation microservice
// For demo purposes, returning mock data
return [
{ userId: 42, score: 0.92, reason: 'Similar interests in technology' },
{ userId: 57, score: 0.87, reason: '3 mutual connections' },
{ userId: 103, score: 0.76, reason: 'Both active in JavaScript community' }
];
}
module.exports = router;
Frontend Implementation
A simple React component to display recommendations:
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import './UserRecommendations.css';
const UserRecommendations = ({ userId }) => {
const [recommendations, setRecommendations] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchRecommendations = async () => {
try {
setLoading(true);
const response = await axios.get(`/api/users/${userId}/recommendations`);
setRecommendations(response.data);
setLoading(false);
} catch (err) {
console.error('Error fetching recommendations:', err);
setError('Failed to load recommendations');
setLoading(false);
}
};
fetchRecommendations();
// Refresh recommendations every 12 hours
const interval = setInterval(fetchRecommendations, 12 * 60 * 60 * 1000);
return () => clearInterval(interval);
}, [userId]);
if (loading) return <div className="recommendations-loading">Loading people you may know...</div>;
if (error) return <div className="recommendations-error">{error}</div>;
if (recommendations.length === 0) return null;
return (
<div className="recommendations-container">
<h3>People You May Want to Connect With</h3>
<div className="recommendations-list">
{recommendations.map(rec => (
<div key={rec.userId} className="recommendation-card">
<img
src={`/api/users/${rec.userId}/avatar`}
alt="User avatar"
className="recommendation-avatar"
/>
<div className="recommendation-details">
<div className="recommendation-name">
{/* In real app, fetch user details */}
User {rec.userId}
</div>
<div className="recommendation-reason">{rec.reason}</div>
<button className="connect-button">Connect</button>
</div>
</div>
))}
</div>
</div>
);
};
export default UserRecommendations;
Performance Considerations
Architecture Diagram
+-------------------+ +-------------------------+ +----------------------+
| | | | | |
| Web Application |<-->| Recommendation API |<-->| Redis Cache |
| | | (Node.js/Python/etc.) | | |
+-------------------+ +-------------------------+ +----------------------+
^ ^
| |
v v
+-------------------+ +-------------------------+ +----------------------+
| | | | | |
| User Activity DB |<-->| Batch Processing Jobs |<-->| ML Feature Store |
| (PostgreSQL) | | (Python/Spark) | | (specialized DB) |
| | | | | |
+-------------------+ +-------------------------+ +----------------------+
The most effective recommendation systems combine multiple approaches:
Here's a simple hybrid scoring function:
def hybrid_recommendation_score(user_id, candidate_id):
# Get scores from different systems
collaborative_score = get_collaborative_score(user_id, candidate_id)
content_score = get_content_similarity_score(user_id, candidate_id)
graph_score = get_graph_connection_score(user_id, candidate_id)
# Business rules
is_premium = is_premium_user(candidate_id)
premium_boost = 1.2 if is_premium else 1.0
# Combine scores (weights determined by A/B testing)
final_score = (
0.5 * collaborative_score +
0.3 * content_score +
0.2 * graph_score
) * premium_boost
return final_score
Key Metrics to Track
A/B Testing Framework
Continuously optimize your recommendation system:
// Simple A/B test setup
const getRecommendationAlgorithm = (userId) => {
// Deterministic assignment based on user ID
const bucket = userId % 3; // 3 test variants
switch(bucket) {
case 0:
return 'collaborative_filtering';
case 1:
return 'content_based';
case 2:
return 'hybrid_approach';
default:
return 'collaborative_filtering';
}
};
// Track which algorithm was shown to user
const trackRecommendationImpression = (userId, algorithmType, recommendedUsers) => {
analytics.track('recommendation_impression', {
userId,
algorithmType,
recommendedUserIds: recommendedUsers.map(r => r.userId),
timestamp: new Date().toISOString()
});
};
// Track when user connects with a recommended user
const trackRecommendationAccepted = (userId, targetUserId, algorithmType) => {
analytics.track('recommendation_accepted', {
userId,
targetUserId,
algorithmType,
timestamp: new Date().toISOString()
});
};
Adding a user-to-user recommendation system isn't just a technical feature—it's a business differentiator that can transform how users experience your platform. Start small, measure results, and continuously refine your approach based on real user behavior.
Explore the top 3 practical use cases of user-to-user recommendation systems for your web app.
User-to-user recommendations power the "People You May Know" feature that drives network growth and engagement. By analyzing existing connection graphs, mutual friends, profile similarities, and interaction patterns, the system can identify high-probability connections users haven't made yet. This creates a virtuous cycle where each new connection strengthens the recommendation engine's predictive capabilities while simultaneously increasing platform stickiness.
In freelance platforms, job boards, or specialized marketplaces, connecting users with complementary skills or expertise creates substantial business value. For example, matching a startup founder seeking UX expertise with designers who have successfully worked with similar early-stage companies, or connecting a homeowner with contractors who have completed similar renovation projects nearby. These recommendations leverage both explicit skills data and implicit signals from past interactions to facilitate transactions that might otherwise never happen.
For platforms focused on professional development, research, or education, strategic user-to-user connections can accelerate learning and innovation. By identifying users working on similar problems or with complementary knowledge bases, the system can suggest mentorships, research partnerships, or study groups. This dramatically increases the platform's value proposition by transforming individual knowledge into collaborative potential, which is particularly powerful for specialized domains where finding the right collaborator is both crucial and challenging.
From startups to enterprises and everything in between, see for yourself our incredible impact.
Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We’ll discuss your project and provide a custom quote at no cost.Â