DEV Community

Ruhul Amin Sujon
Ruhul Amin Sujon

Posted on • Edited on

Laravel IQ - Level 1 - Part 5

প্রশ্ন ১: আমার ম্যানুবার ডাটাবেইজ এ সেভ আছে & cache use করে লোড করাই। এখন আমি আবার নতুন একটা মেনুবার এড করলাম, ওই লগিন করা ইউজার রিয়েল টাইমে কিভাবে মেনুটা পাবে? best approach টা বলো আমাকে?

উত্তর:

🧠 Problem Recap (তুমি যা বলছো)

  • Menu DB তে সেভ করা
  • Performance এর জন্য cache থেকে menu load করছো
  • ❓ এখন নতুন menu add করলে, 👉 already login করা user কীভাবে** real-time** নতুন menu পাবে?

🎯 Short Answer (Interview-Ready):

Best approach হলো:
👉 Cache Invalidation + Event/Broadcast (WebSocket) + Smart Frontend Refresh
সব ক্ষেত্রে full real-time socket দরকার হয় না — requirement অনুযায়ী solution নিতে হয়।


Best Approaches (Priority অনুযায়ী)

আমি তোমাকে ৩টা practical approach দেবো — production-ready।


🥇 Approach 1: Cache Invalidation + Next Request Reload (MOST COMMON & BEST)
🔹 Concept:

  • Menu add/update/delete হলে menu cache clear
  • User এর next request এ menu আবার DB থেকে load হয়ে cache হবে
  • Simple, scalable, safe

🔹 Backend Example:

// MenuController.php
public function store(Request $request)
{
    Menu::create($request->all());


    Cache::forget('menus'); // 🔥 cache invalidate
}
Enter fullscreen mode Exit fullscreen mode

🔹 Menu Load:

$menus = Cache::remember('menus', 3600, function () {
    return Menu::active()->get();
});
Enter fullscreen mode Exit fullscreen mode

🔹 Result:

  • User page reload / API call করলেই নতুন menu পাবে
  • 90% SaaS, ERP, Admin panel এ এটাই ব্যবহার হয়

Pros

  • Simple
  • No extra infra
  • Highly scalable

Cons

  • Strict “real-time” না (reload লাগবে)

👉 If requirement না বলে “instant live without reload”THIS IS BEST


🥈 Approach 2: Event + Broadcast (Real-Time without reload)

যদি requirement হয়:

“Admin menu add করলেই user instant menu পাবে (no refresh)”

তাহলে 👇


🔹 Flow:

Admin adds menu
 → MenuCreated Event
 → Cache clear
 → Broadcast event
 → Frontend listens
 → Menu API refetch
Enter fullscreen mode Exit fullscreen mode

🔹 Backend: Event

event(new MenuUpdated());
Enter fullscreen mode Exit fullscreen mode

🔹 Event Class:

class MenuUpdated implements ShouldBroadcast
{
    public function broadcastOn()
    {
        return new Channel('menu-channel');
    }
}
Enter fullscreen mode Exit fullscreen mode

🔹 Frontend (Vue / JS example):

Echo.channel('menu-channel')
    .listen('MenuUpdated', () => {
        fetchMenus(); // API call করে নতুন menu আনবে
    });
Enter fullscreen mode Exit fullscreen mode

🔹 Result:

  • User login অবস্থাতেই menu auto update
  • No reload needed

Pros

  • Real-time UX
  • Modern feel

Cons

  • Redis / WebSocket setup
  • Complexity বেশি

👉 Use when:
Dashboard / POS / Live admin systems


🥉 Approach 3: Cache Versioning (Very Smart & Scalable)

🔥 এটা senior-level trick


🔹 Concept:

  • Menu cache key এর সাথে version যুক্ত করো
  • Menu update হলে version change
  • Old cache auto-ignore হয়ে যাবে

🔹 Example:

$version = Cache::get('menu_version', 1);


$menus = Cache::remember("menus_v{$version}", 3600, function () {
    return Menu::all();
});
Enter fullscreen mode Exit fullscreen mode

🔹 Menu update হলে:

Cache::increment('menu_version');
Enter fullscreen mode Exit fullscreen mode

🔹 Result:

  • No need to flush cache
  • Zero race condition
  • Highly scalable

Pros

  • Clean architecture
  • Multi-server safe

Cons

  • একটু advanced thinking লাগে

👉 Use when:
Large-scale SaaS / multi-tenant system


What NOT to do (Bad Practice)

🚫 Cache::flush()
🚫 Every second polling
🚫 Force logout users
🚫 DB hit on every request


🎯 Interview Killer Answer (1–2 lines):

Menu update হলে আমি menu cache invalidate করি।
Real-time দরকার হলে Laravel Event + Broadcast ব্যবহার করে frontend কে menu refetch করতে বলি।
Large system হলে cache versioning strategy ব্যবহার করি।

প্রশ্ন 2: Production এ redis configure কিভাবে?
i. shared hosing (c-panel),
ii. VPS ,
iii. AWS & after production configure ,
.env তে কি কি change করতে হবে?

উত্তর:

Production-এ Redis Configure করার পূর্ণ গাইড (Laravel)

আমি ৩টা environment আলাদা করে বলবো:

1️⃣ Shared Hosting (cPanel)
2️⃣ VPS (DigitalOcean / Contabo / Vultr ইত্যাদি)
3️⃣ AWS (EC2 / ElastiCache)

তারপর বলবো 👉 .env-এ কী কী change করতে হবে


🧠 আগে বুঝে নাও: Laravel Redis কেন ব্যবহার করে?

Laravel Redis ব্যবহার করে:

  • Cache
  • Queue
  • Session
  • Broadcast
  • Rate limiting

🟡 i. Shared Hosting (cPanel) এ Redis Configure

⚠️ Reality check:
সব shared hosting এ Redis support করে না।

Prerequisites:

  • Hosting provider Redis enable করে দিতে হবে
  • PHP Redis extension (phpredis) enabled থাকতে হবে

🔹 Step 1: cPanel → Redis Enable

  • cPanel → Select PHP Version
  • Extensions → ✔️ redis
  • Save

🔹 Step 2: Laravel .env config

CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis


REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
Enter fullscreen mode Exit fullscreen mode

📌 Shared hosting এ সাধারণত:

  • REDIS_HOST=127.0.0.1
  • Password থাকে না

🔹 Step 3: config clear

php artisan config:clear
php artisan cache:clear
Enter fullscreen mode Exit fullscreen mode

Limitation (Shared Hosting):

  • Redis restart control নেই
  • Performance limited
  • Queue worker চালানো যায় না

👉 Small project / cache only হলে OK


🟢 ii. VPS-এ Redis Configure (BEST PRACTICE)

এইটা সবচেয়ে common & professional setup।


🔹 Step 1: Redis Install (Ubuntu)

sudo apt update
sudo apt install redis-server
Enter fullscreen mode Exit fullscreen mode

🔹 Step 2: Redis Secure & Optimize

sudo nano /etc/redis/redis.conf
Enter fullscreen mode Exit fullscreen mode

Change:

supervised systemd
bind 127.0.0.1
requirepass strongpassword
Enter fullscreen mode Exit fullscreen mode

Restart:

sudo systemctl restart redis
sudo systemctl enable redis
Enter fullscreen mode Exit fullscreen mode

Check:

redis-cli ping
# PONG
Enter fullscreen mode Exit fullscreen mode

🔹 Step 3: PHP Redis Extension Install

sudo apt install php-redis
sudo systemctl restart php8.2-fpm
Enter fullscreen mode Exit fullscreen mode

🔹 Step 4: Laravel .env

CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis


REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=strongpassword
REDIS_PORT=6379
Enter fullscreen mode Exit fullscreen mode

🔹 Step 5: Queue Worker (Production MUST)

php artisan queue:work --daemon
Enter fullscreen mode Exit fullscreen mode

Or better:

sudo supervisorctl start laravel-worker
Enter fullscreen mode Exit fullscreen mode

VPS Advantages:

  • Full control
  • Best performance
  • Redis + Queue + Horizon সব possible

👉 Recommended for SaaS / ERP / API


🔵 iii. AWS-এ Redis Configure

AWS-এ ২টা option থাকে:


🔹 Option A: Redis inside EC2 (VPS-like)

Exactly VPS-এর মতোই setup
👉 Not recommended for production scale


🔹 Option B: AWS ElastiCache (BEST PRACTICE)**

✔️ Managed Redis
✔️ Auto scaling
✔️ High availability


🔹 Step 1: Create ElastiCache Redis

  • AWS Console → ElastiCache
  • Engine: Redis
  • Node type: cache.t3.micro (small)
  • Enable Auth Token

🔹 Step 2: Security Group

  • Allow Redis port 6379
  • Only from EC2 private IP

🔹 Step 3: Laravel .env

CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis


REDIS_CLIENT=phpredis
REDIS_HOST=redis-cluster.xxxxxx.cache.amazonaws.com
REDIS_PASSWORD=auth-token
REDIS_PORT=6379
Enter fullscreen mode Exit fullscreen mode

📌 Important:
EC2 + Redis must be in same VPC


AWS Redis Benefits:

  • Zero maintenance
  • Auto failover
  • Production-grade

👉 Enterprise / high traffic app এর জন্য BEST


🔧 Production .env – Common Redis Config

CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis


REDIS_CLIENT=phpredis
REDIS_HOST=
REDIS_PASSWORD=
REDIS_PORT=6379
Enter fullscreen mode Exit fullscreen mode

Optional (multiple DB):

REDIS_DB=0
REDIS_CACHE_DB=1
Enter fullscreen mode Exit fullscreen mode

Common Mistakes (Interview Trap ⚠️)

🚫 Cache::flush() production এ
🚫 Redis open to public IP
🚫 .env change করে config clear না করা
🚫 Queue worker না চালানো


🏆 Which Setup Should You Choose?

🎯 Interview-Ready One-Line Answer:

Production-এ Redis configure করতে আমি environment অনুযায়ী setup করি।
VPS-এ Redis server install করে .env-এ cache, session, queue redis করি।
AWS-এ ElastiCache ব্যবহার করি scalability ও reliability এর জন্য।

প্রশ্ন 3: আমার ১ মতো মিলিয়ন ডাটা আছে। আমাকে একটা পেজেই দেখাতে হবে। chunk ব্যবহার করা ভালো হবে নাকি ajax ব্যবহার করা ভালো হবে?

উত্তর:

সংক্ষিপ্ত উত্তর 👉 chunk না, AJAX (pagination / lazy loading / infinite scroll)
এখন বিস্তারিতভাবে কেন সেটা বুঝিয়ে দিচ্ছি।


🔥 মূল কথা (Very Important)

👉 ১ মিলিয়ন ডাটা এক পেজে একসাথে দেখানো বাস্তবে অসম্ভব ও ভুল ডিজাইন
এটা করলে:

  • Server memory crash হতে পারে
  • Browser hang করবে
  • User experience ভয়াবহ হবে

🧩 Chunk vs AJAX – আসলে কোনটা কী কাজে?
🔹 Chunk কী?

chunk() ব্যবহার হয় server-side data processing এর জন্য
👉 UI-তে ডাটা দেখানোর জন্য না

User::chunk(1000, function ($users) {
    foreach ($users as $user) {
        // process data (email, export, update)
    }
});
Enter fullscreen mode Exit fullscreen mode

✔ Memory safe
❌ Frontend rendering-এর জন্য নয়


🔹 AJAX কী?

AJAX ব্যবহার হয় frontend-এ ধাপে ধাপে data লোড করার জন্য

fetch('/users?page=2')
Enter fullscreen mode Exit fullscreen mode

✔ Fast UI
✔ Scalable
✔ Real-world solution


সঠিক Solution Architecture (Best Practice)
Option 1: Pagination (সবচেয়ে recommended)

$users = User::paginate(50);
Enter fullscreen mode Exit fullscreen mode

Frontend:

{{ $users->links() }}
Enter fullscreen mode Exit fullscreen mode

✔ Simple
✔ SEO friendly
✔ Production safe


Option 2: AJAX Pagination (Modern UX)

$users = User::paginate(50);
return response()->json($users);
Enter fullscreen mode Exit fullscreen mode

JS দিয়ে page load

✔ Smooth experience
✔ No page reload


Option 3: Infinite Scroll / Lazy Load

$users = User::cursorPaginate(50);
Enter fullscreen mode Exit fullscreen mode

✔ Facebook / YouTube style
✔ Large data friendly

🚀 Extra Optimization (1 million data হলে MUST)
Index ব্যবহার

CREATE INDEX idx_created_at ON users(created_at);
Enter fullscreen mode Exit fullscreen mode

cursorPaginate (pagination এর চেয়ে fast)

User::cursorPaginate(100);
Enter fullscreen mode Exit fullscreen mode

Select only required columns

User::select('id','name')->cursorPaginate(50);
Enter fullscreen mode Exit fullscreen mode

🧠 Interview Ready Answer:

> chunk() server-side heavy processing-এর জন্য, আর ১ মিলিয়ন ডাটা UI-তে দেখানোর জন্য AJAX pagination / lazy loading ব্যবহার করা উচিত।

🏁 Final Recommendation (Your Case)

👉 AJAX + cursor pagination + proper indexing
👉 কখনোই ১ মিলিয়ন row এক পেজে render করবে না

প্রশ্ন 4: কিন্তু ক্লায়েন্টের রিকয়ারমেন্ট হলো ফেসবুক পোস্টের মতো স্ক্রল করে ডেটা লোড করা। অর্থাৎ, স্ক্রল করার সাথে সাথে অনবরত পোস্ট লোড হতে থাকবে এবং প্রদর্শিত হবে। তারা এই লিস্টের ক্ষেত্রেও ঠিক একই জিনিস চাচ্ছে। আমি এটি কীভাবে করতে পারি?

উত্তর:

এটা আসলে Facebook-style Infinite Scroll requirement 👍
এই ক্ষেত্রে AJAX + Cursor Pagination ব্যবহার করাই একমাত্র production-safe solution।
আমি পুরো flow + Laravel + JS example দিয়ে বুঝিয়ে দিচ্ছি।


🧠 Core Idea (Facebook যেভাবে করে)

❌ একবারে ১ মিলিয়ন ডাটা লোড না
প্রথমে অল্প ডাটা
Scroll করলে পরের ডাটা
✅ User বুঝতেই পারে না যে backend-এ pagination চলছে

🏗️ Architecture (High Level)

Browser scroll
   ↓
AJAX request (cursor / page)
   ↓
Laravel API
   ↓
Database (indexed)
   ↓
JSON response
   ↓
Append to DOM
Enter fullscreen mode Exit fullscreen mode

Step 1: Database Optimization (Must)

👉 যেই column দিয়ে order করবে, সেটাতে index লাগবে

CREATE INDEX idx_id ON posts(id);
Enter fullscreen mode Exit fullscreen mode

Facebook-style feed সাধারণত:

ORDER BY id DESC
Enter fullscreen mode Exit fullscreen mode

Step 2: Laravel Controller (cursorPaginate)

👉 paginate() না, cursorPaginate() ব্যবহার করো (১ মিলিয়নের জন্য best)

public function posts(Request $request)
{
    $posts = Post::select('id', 'title', 'body')
        ->orderByDesc('id')
        ->cursorPaginate(10);

    return response()->json($posts);
}
Enter fullscreen mode Exit fullscreen mode

📌 কেন cursorPaginate?

  • OFFSET ব্যবহার করে না
  • Large dataset-এ fast
  • Memory efficient

Step 3: Route

Route::get('/posts', [PostController::class, 'posts']);
Enter fullscreen mode Exit fullscreen mode

Step 4: Frontend HTML

<div id="post-container"></div>
<div id="loader">Loading...</div>
Enter fullscreen mode Exit fullscreen mode

Step 5: JavaScript (Infinite Scroll)

let nextPageUrl = '/posts';

function loadPosts() {
    if (!nextPageUrl) return;

    fetch(nextPageUrl)
        .then(res => res.json())
        .then(data => {
            data.data.forEach(post => {
                document.getElementById('post-container')
                    .insertAdjacentHTML(
                        'beforeend',
                        `<div class="post">
                            <h4>${post.title}</h4>
                            <p>${post.body}</p>
                        </div>`
                    );
            });

            nextPageUrl = data.next_page_url;
            document.getElementById('loader').style.display = 'none';
        });
}

window.addEventListener('scroll', () => {
    if (
        window.innerHeight + window.scrollY >= document.body.offsetHeight - 200
    ) {
        document.getElementById('loader').style.display = 'block';
        loadPosts();
    }
});

// First load
loadPosts();
Enter fullscreen mode Exit fullscreen mode

🔥 Result

✔ First page loads fast
✔ Scroll করলে auto load
✔ User মনে করে সব এক পেজেই আছে
✔ Backend safe even with 1M rows


⚠️ Important Production Tips
1️⃣ Throttle AJAX calls

let loading = false;
if (loading) return;
loading = true;
Enter fullscreen mode Exit fullscreen mode

2️⃣ Stop when no data

if (!nextPageUrl) {
    loader.innerText = 'No more posts';
}
Enter fullscreen mode Exit fullscreen mode

3️⃣ Cache (Optional)

Cache::remember("posts_{$cursor}", 30, fn() => $posts);
Enter fullscreen mode Exit fullscreen mode

🧠 Interview-Ready Explanation:

Facebook-style infinite scroll করতে AJAX + cursor pagination ব্যবহার করা হয়।
এতে large dataset efficiently load হয়, offset query এড়ানো যায়, এবং smooth UX পাওয়া যায়।


🏁 Final Recommendation (Exactly your case)

✅ AJAX
✅ cursorPaginate()
✅ Indexed column
✅ Infinite scroll JS

Top comments (0)