惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
WordPress大学
WordPress大学
博客园 - 【当耐特】
Engineering at Meta
Engineering at Meta
IT之家
IT之家
Apple Machine Learning Research
Apple Machine Learning Research
小众软件
小众软件
美团技术团队
S
SegmentFault 最新的问题
The GitHub Blog
The GitHub Blog
Martin Fowler
Martin Fowler
Recorded Future
Recorded Future
H
Help Net Security
aimingoo的专栏
aimingoo的专栏
Y
Y Combinator Blog
博客园_首页
A
About on SuperTechFans
MongoDB | Blog
MongoDB | Blog
阮一峰的网络日志
阮一峰的网络日志
V
Visual Studio Blog
D
DataBreaches.Net
人人都是产品经理
人人都是产品经理
大猫的无限游戏
大猫的无限游戏
B
Blog
The Register - Security
The Register - Security
I
InfoQ
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
雷峰网
雷峰网
Last Week in AI
Last Week in AI
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
月光博客
月光博客
酷 壳 – CoolShell
酷 壳 – CoolShell
Blog — PlanetScale
Blog — PlanetScale
N
Netflix TechBlog - Medium
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
有赞技术团队
有赞技术团队
Stack Overflow Blog
Stack Overflow Blog
Jina AI
Jina AI
Security Archives - TechRepublic
Security Archives - TechRepublic
Hacker News - Newest:
Hacker News - Newest: "LLM"
U
Unit 42
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
W
WeLiveSecurity
Latest news
Latest news
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
博客园 - 叶小钗
L
Lohrmann on Cybersecurity
博客园 - Franky
Recent Commits to openclaw:main
Recent Commits to openclaw:main
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
How to Create a High-Traffic Laravel App (Practical Guide)
Yogesh Galav · 2026-05-02 · via DEV Community

Building a Laravel app is easy. Building one that still feels fast when real users panic-click vote like it is an elevator button—that is where the real game starts 😄 This guide ties good habits (and a little paranoia) to this polling app codebase: admin poll CRUD, guest-friendly “one ballot” rules, cached poll feeds, and Echo + VoteCountUpdated so bars move on both the public poll page and the admin results screen—because “live counts” stops being fun when only half the tabs believe you.

Concrete entry points worth bookmarking (Ctrl+click responsibly 🙌):

Start simple, but think ahead 🚀

The hottest path here is POST /polls/{poll}/vote: validation, locking, transactional insert + counter bump, broadcast, optional feed-cache patch. The next hottest is GET /polls/feed and the homepage index—both funnel through PublicPollController::pollFeed and cache for early pages (cachedPollIds + per-poll keys). Design those first; nobody’s portfolio got famous because the settings page shaved 8 ms ✅


Protect the app from repeated actions 🛡️

Humans spam buttons. Bots spam endpoints. Laravel rate limiters quietly flex “not today”—use them 👀

The vote route registers a named limiter poll-vote:

Route::post('/polls/{poll}/vote', [PublicPollController::class, 'vote'])->name(
    'polls.vote',
)->middleware('throttle:poll-vote');

Enter fullscreen mode Exit fullscreen mode

The limit itself keys off a stable poll device cookie (PollDeviceId::get), falling back to IP if the cookie is empty—so testers on the same LAN are not artificially merged:

        RateLimiter::for("poll-vote", function (Request $request) {
            $deviceId = PollDeviceId::get($request);

            return Limit::perSecond(3)->by($deviceId !== "" ? $deviceId : $request->ip());
        });

Enter fullscreen mode Exit fullscreen mode

The device id cookie name is poll_device_id; it is exempted from Laravel’s encrypted-cookie middleware so SPA requests can behave predictably (PollDeviceId::COOKIE_NAME in bootstrap/app.php). Middleware EnsurePollDeviceId ensures guests get an id cookie.

Ship the same idea anywhere a single POST suddenly becomes everyone’s hobby under burst traffic.


Stop duplicate votes at both levels 🔒

Controllers have dreams; databases have veto power. Never trust only the happy path 💡

This repo stacks three walls behind the UX so “I clicked twice” does not graduate into “two rows exist” 😬

1 — Cache lock keyed by poll and guest, so overlapping clicks serialize before touching the DB (wait 3 seconds before LockTimeoutException):

        $lockKey = "poll:{$poll->id}:guest:{$guest->id}:vote";
        $lockTtlSeconds = 10;
        $waitSeconds = 3;

        try {
            $result = Cache::lock($lockKey, $lockTtlSeconds)->block(
                $waitSeconds,

Enter fullscreen mode Exit fullscreen mode

Inside the closure: already_voted gated on votes.deleted_at (soft deletes).

2 — Transaction plus lockForUpdate() on the poll option, then Vote::create(...) and $option->increment('votes_count') so the tally and row stay coherent:

                        DB::transaction(function () use ($poll, $guest, $pollOptionId): void {
                            $option = PollOption::query()
                                ->whereKey($pollOptionId)
                                ->where('poll_id', $poll->id)
                                ->lockForUpdate()
                                ->firstOrFail();

                            Vote::query()->create([
                                'poll_id' => $poll->id,
                                'poll_option_id' => $option->id,
                                'guest_id' => $guest->id,
                            ]);

                            $option->increment('votes_count');
                        });

Enter fullscreen mode Exit fullscreen mode

3 — Unique index on (poll_id, guest_id) plus mapping 23000 to already voted if two workers still collide:

        Schema::create("votes", function (Blueprint $table) {
            $table->id();
            $table
                ->foreignId("poll_id")
                ->constrained("polls")
                ->cascadeOnDelete();
            // ...
            $table->unique(["poll_id", "guest_id"]);
        });

Enter fullscreen mode Exit fullscreen mode

PublicPollController::vote translates outcomes into chill 201 energy, grouchy-but-fair 403 duplicates, or 429 “breathe—someone beat you to that lock”—see PublicPollController.php for the blunt HTTP poetry ✍️


Use database transactions for related writes 🧾

Half-created polls age like milk; users only notice when the percentages look like astrology ✨

Votes: covered above (DB::transaction inside the lock closure).

Poll create and update also run in transactions in PollApiController—slug derivation, $poll->options()->create(...), and update paths that reconcile options and votes (store / update both wrap DB::transaction(...)). All-or-nothing beats “poll exists but options went on strike.”


Real-time is nice—but correctness comes first ⚡

“Live” stops being delightful when admins refresh like it is still 2009 🔁 ShouldBroadcastNow means Pusher earns its lunch inside the PHP request—which is totally fine until your workers start giving you emotional damage.

The event broadcasts on polls.{pollId} as votes.updated and implements ShouldBroadcastNow (broadcast runs inline with the HTTP request unless you refactor to queued broadcasts):

class VoteCountUpdated implements ShouldBroadcastNow
{
    // ...
    public function broadcastOn(): Channel
    {
        return new Channel("polls.{$this->pollId}");
    }

    public function broadcastAs(): string
    {
        return "votes.updated";
    }
}

Enter fullscreen mode Exit fullscreen mode

Echo is wired from resources/js/bootstrap.js (Pusher driver + env keys). CastPollVoteAction ends with broadcast(new VoteCountUpdated(...)) after refreshCachedPollAfterVote.

Clients apply the payload the same way in two places—the public poll page:

const channelName = `polls.${props.poll.id}`;

function applyVoteCountUpdate(payload) {
    // ... maps payload.totalVotes and payload.options into poll.value ...
}

onMounted(() => {
    window.Echo?.channel(channelName).listen('.votes.updated', applyVoteCountUpdate);
});

onBeforeUnmount(() => {
    window.Echo?.leave(channelName);
});

Enter fullscreen mode Exit fullscreen mode

…and the admin results screen:

const channelName = `polls.${props.poll.id}`;
// ...
onMounted(() => {
    window.Echo?.channel(channelName).listen('.votes.updated', applyVoteCountUpdate);
});

Enter fullscreen mode Exit fullscreen mode

The voter’s POST response still returns JSON counts so the UI upgrades before the websocket finishes its iced coffee ☕️—see PublicPollController::vote and the axios onVote handler in Show.vue.


Be careful with queues 🤔 (ProcessPollVote is optional here)

Queues are heroic for mailers and thumbnails; they are chaotic for anything that wears a neon “I am the product moment” badge.

ProcessPollVote (ShouldQueue, ShouldBeUnique) exists as an optional spike for async processing; PublicPollController::vote currently calls CastPollVoteAction::execute and broadcasts from there—honest 201, jealous queue optional 🧠

If you enqueue votes anyway:

  • Tune retries, dead-letter / failed-job visibility, afterCommit dispatch, and broadcaster timing so “live” viewers are not fooled by rollback or lag.
  • Make handlers idempotent (your unique (poll_id, guest_id) row already helps).

Use queues aggressively for ancillary Laravel chores—in this repo the natural next flex is migrating VoteCountUpdated off ShouldBroadcastNow onto ShouldBroadcast when your PHP-FPM graphs start looking like roller coasters 🎢


Caching helps, but stale data hurts 🧹

Caches are cheatsheets, not confession booths—votes move fast enough that Cache::rememberForever + wishful thinking is how trust dies 👻

Warm path here: CachedPollIds::LIMIT (50) ordered ids stored under CachedPollIds::KEY, TTL in CachedPollIds.php. cachedPoll payloads live at poll:{id}.

  • PollObserver (registered in AppServiceProvider) pushes new/edited polls into the id list after commit and rewrites poll:{id} cache entries app/Observers/PollObserver.php.
  • CastPollVoteAction::refreshCachedPollAfterVote increments counts inside cached poll:{id} when that poll sits in CachedPollIds, avoiding a blunt “delete every poll key” on each vote app/Actions/Polls/CastPollVoteAction.php.

VoteRepo::appendGuestVotes bulk-loads votes rows for whereIn poll_id and merges voted_option_id (+ reconciled counts when voted) onto feed rows—no N+1 tourism 🚌


Keep controllers thin (not “empty,” just not a junk drawer) 🙂

If your controller reads like a novella starring seven concerns, give it therapy—split Actions, Responses, repos, literally anything with a spine 📖

PublicPollController stitches Inertia payloads, VoteRequest validation (see VoteRequest), and delegates voting to CastPollVoteAction. Feed assembly uses VoteRepo + FeedPollResponse / ShowPollResponse.

Admin pages use PollPageController; JSON shapes go through PollApiController with StorePollRequest / UpdatePollRequest. Policies are wired on routes with ->can(...):

        Route::get('polls', [PollPageController::class, 'index'])
            ->name('polls.index')
            ->can('viewAny', Poll::class);

        Route::get('polls/create', [PollPageController::class, 'create'])
            ->name('polls.create')
            ->can('create', Poll::class);
        // ... viewResults / update bindings ...

Enter fullscreen mode Exit fullscreen mode

PollPolicy is registered in AppServiceProvider.


Validation deserves respect ✅

Rules belong in FormRequest classes so controllers stay readable and regressions hurt your feelings in PHPUnit instead of in prod logs 🌱

Prefer Form Requests over inline validation—in this tree, voting uses VoteRequest; admin create/update uses StorePollRequest / UpdatePollRequest.

When an admin changes an existing option label, PollApiController::update soft-deletes only votes linked to that option (see Vote::query()->where(...)->where('poll_option_id', $existing->id)) so aggregates stay honest; untouched options retain their votes app/Http/Controllers/Polls/Admin/PollApiController.php.

Product rule: freeze polls like museum exhibits or own the cleanup story—floating policy is how PMs haunt Slack 😐


Index the queries that actually run 📚

If your migration only has vibes, MySQL spends coffee money on full scans—index with intent, not superstition 👌

The migration votes adds unique(['poll_id', 'guest_id']) implicitly indexing lookup patterns you touch every vote. FK columns (poll_id, poll_option_id, guest_id) piggyback InnoDB indexing for joins and deletes. polls.slug is unique in database/migrations/2026_04_13_102438_create_polls_table.php—nice for Route::get('/polls/{poll:slug}', ...) and humane URLs.

Reach for EXPLAIN before you spray composite indexes everywhere.


Plan for traffic spikes honestly 📈

If your scaling plan stops at “horizon scales, bro”, you owe your future self an apology 🔍 Laravel won’t politely negotiate with 1M votes on a tiny host—you name the weakest layer.

Ask what hits first for your deployment: relational write throughput (votes + poll_options.votes_count), Cache::lock dogpiles, Pusher / broadcast quotas, ShouldBroadcastNow stretching PHP fingers, cheap CPU—the answer should come from artisan/load tests, not vibes.

Multi-tenant SaaS (not modeled here) stays a parallel design: tenant column vs schema vs DB-per-tenant is a compliance and ops tradeoff independent of Laravel version.


Test the whole flow, not just the happy screenshot 🧪

Green CI is nice; angry QA with two browsers incognito hits different tests/Feature/PollVotingTest.php moods—covers duplicates, broadcasts, Guest identity, CastPollVoteAction edge cases where applicable, admin option edits versus votes, CSRF/session quirks, etc. Extend it whenever you tighten locking or caching so regressions bruise phpunit first 🙏


Build trust with plain decisions ❤️

Scratchpad cheat sheet 🎯

  • polls.vote stays honest: throttle 🛡️, cache lock 🔒, transaction 🧾, unique DB constraint, boring HTTP statuses PublicPollController · CastPollVoteAction.
  • Feed caches stay purposeful: CachedPollIds + poll:{id} + PollObserver + surgical vote patches—no FLUSH ALL drama CachedPollIds · PollObserver.
  • Broadcast after reality matches: Show.vue and Results.vue both subscribe—admins deserve live bars too ⚡️ VoteCountUpdated.
  • README knows your .env secrets (Pusher/Vite)—future-you sends thanks README.md.

A Laravel app that feels high-traffic is rarely one genius shortcut—it is stacks of mildly boring safeguards that jokes cannot replace 😄 Ship the paranoia and ship the laughs; your queue workers cannot file HR complaints anyway 💼