Social Graph Scalabile: Gestione Follower, Following e Feed con Laravel & Swift

Il cuore di qualsiasi piattaforma social è il suo Social Graph: la rete di connessioni unidirezionali o bidirezionali che unisce gli utenti attraverso relazioni di "Segui" (Follower / Following). Quando l'applicazione cresce e supera decine di migliaia di utenti, calcolare il feed e i contatori al volo con semplici query COUNT(*) diventa rapidamente un collo di bottiglia per le prestazioni del database.

1. Struttura della Tabella Relazionale in PostgreSQL

La tabella follows deve essere indicizzata su entrambe le direzioni per consentire query sub-millisecondo:

CREATE TABLE follows (
    id BIGSERIAL PRIMARY KEY,
    follower_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    following_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT unique_follow_pair UNIQUE (follower_id, following_id)
);

CREATE INDEX idx_follows_follower ON follows(follower_id);
CREATE INDEX idx_follows_following ON follows(following_id);

2. Gestione Toggle Follow Atomica con Notifica Push

Nel backend Laravel, l'azione di Follow/Unfollow esegue il toggle atomico e notifica l'utente target:

<?php

namespace App\Http\Controllers;

use App\Models\Follow;
use App\Models\User;
use App\Services\ApnsService;
use Illuminate\Http\Request;

class FollowController extends Controller
{
    public function toggle(Request $request, $targetUserId)
    {
        $viewer = $request->user();
        $targetUser = User::findOrFail($targetUserId);

        if ($viewer->id === $targetUser->id) {
            return response()->json(['error' => 'Non puoi seguire te stesso'], 400);
        }

        $existing = Follow::where('follower_id', $viewer->id)
            ->where('following_id', $targetUser->id)
            ->first();

        if ($existing) {
            $existing->delete();
            $isFollowing = false;
        } else {
            Follow::create([
                'follower_id' => $viewer->id,
                'following_id' => $targetUser->id,
            ]);
            $isFollowing = true;

            // Invia notifica push APNs
            ApnsService::sendToUser(
                $targetUser,
                "Nuovo Follower 👤",
                "{$viewer->name} ha iniziato a seguirti.",
                ['type' => 'follow', 'user_id' => $viewer->id]
            );
        }

        return response()->json([
            'is_following' => $isFollowing,
            'followers_count' => $targetUser->followers()->count(),
            'following_count' => $targetUser->following()->count(),
        ]);
    }
}

Stai creando una piattaforma social o una community online?

Progettiamo social graph scalabili su cloud con PostgreSQL, Redis Caching e client nativo iOS in SwiftUI.