Skip to content
FR EN
Contact
All articles

Laravel + VueJS: a proven stack for admissions

Dev 5 min

An admissions platform has a very particular load profile: quiet for weeks, then a wave of candidates in the last days before the deadline, often on unstable mobile connections. That is exactly when any weakness costs the most: an application saved twice, a payment left unmatched, a server that stops responding the night before closing. This article explains how a Laravel (API) and VueJS (interface) stack meets these constraints, based on the official Laravel 12 documentation.

Learning objectives

  • understand why a web request must stay short, and how queues make that possible;
  • rate-limit a sensitive route with Laravel’s rate limiter;
  • guarantee the idempotency of a registration, so that a double submission does not create two applications;
  • prepare for a load peak with load testing and monitoring.

1. The mental model: a request must be short

A web server handles requests with a limited number of processes. If each one stays busy for several seconds (generating a PDF notice, sending an email, calling a payment provider’s API), the queue of waiting requests grows and the site appears to « go down », even though the machine is not short of computing power. The rule is therefore: the request saves what matters and responds; everything else is deferred.

Laravel’s documentation puts it this way: queues let you move time-intensive tasks to the background so your application can respond to web requests with blazing speed.

2. Queues in practice

A job is a class describing a deferred task. On registration, the application is saved to the database, then the receipt generation and email are dispatched:

// Controller: respond fast.
$application = Application::create($validatedData);
GenerateReceipt::dispatch($application);

return response()->json(['number' => $application->number], 201);

On the server, worker processes consume the queue. With the Redis driver, faster than the database for this role, they run under Supervisor, which restarts them if they stop. The documentation suggests a configuration like this:

[program:laravel-worker]
command=php /var/www/admissions/artisan queue:work --sleep=3 --tries=3 --max-time=3600
numprocs=8
autostart=true
autorestart=true
stopwaitsecs=3600

Three settings are worth understanding:

  • --tries=3: a failing job is retried, then stored in the failed_jobs table, where it can be inspected and retried;
  • backoff: the delay between attempts, which can grow (for example [1, 5, 10] seconds) so you do not hammer a third-party service that is already struggling;
  • numprocs: the number of parallel workers, sized to the server. Laravel Horizon lets you manage these settings and watch your queues from a dashboard.

3. Rate-limiting sensitive routes

A public registration form also attracts bots. Laravel provides a rate limiter declared in AppServiceProvider:

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;

public function boot(): void
{
    RateLimiter::for('registration', function (Request $request) {
        return Limit::perMinute(10)->by($request->ip());
    });
}

Attach it to the route with the throttle:registration middleware. Past the threshold, Laravel returns HTTP 429 (Too Many Requests), which the interface should turn into a clear message rather than a generic error. For jobs, the RateLimited middleware plays the same role towards an external service: a job that exceeds the limit is released back onto the queue with a delay.

4. Idempotency: a double click must not create two applications

This is the most important property, and the most often overlooked. A candidate on a shaky connection clicks twice; the browser resubmits the form; the payment provider calls your webhook again. Each time, the result must be the same as with a single submission. Combine three levels:

  1. The database, the last line of defence: a unique constraint (for instance on the pair ID document number and exam session) makes the duplicate physically impossible.
  2. The code: a transaction wraps the creation of the application and its attachments, so an error halfway through does not leave a half-created record.
  3. The jobs: the ShouldBeUnique interface ensures that a given job (for example matching a payment) is on the queue only once; the WithoutOverlapping middleware prevents two simultaneous runs on the same key.

Remember the hierarchy: the interface reduces duplicates, the code avoids them, the database forbids them.

5. The role of VueJS: an interface that protects the server

A VueJS single-page application is not just pleasant to use. Well designed, it reduces load and improves data quality:

  • immediate validation of fields (phone number format, attachment size) before anything is sent, server-side validation remaining mandatory;
  • a submit button disabled while sending, the first defence against double clicks;
  • draft saving in the browser, so a network drop does not wipe out twenty minutes of typing;
  • explicit handling of 422 (validation) and 429 (too many requests) errors, with a message that says what to do.

6. Prepare for the peak rather than suffer it

Two practices separate a platform that holds from one that hopes to hold:

  • Load testing before opening: a tool such as k6 simulates hundreds of simultaneous users on the registration flow and reveals the first bottleneck, often an unindexed SQL query.
  • Monitoring during the campaign: queue sizes, failed jobs, response times, disk space. A dashboard checked every morning beats an alert received too late.

Finally, cache reference data that does not change during the campaign (programmes, exam centres) with Cache::remember: these are often the most frequent queries.

Common mistakes

  • Sending emails during the registration request.
  • Relying only on a disabled button to prevent duplicates.
  • Discovering how the platform behaves under load on deadline day.
  • Forgetting to monitor the failed jobs table: a receipt never sent is a worried candidate on the phone.

Key takeaway

Short requests, deferred work, rate limits, idempotency enforced by the database, load tested in advance: these five principles, more than the choice of framework, are what keep an admissions platform standing.

References

We would love to hear your experience

Did you make different choices? Run into other difficulties? Share your experience or your questions in the comments: we read and answer every message.

Leave a comment

Need a custom business application?

Admissions platforms, staff management, AI assistants, e-learning: we design, deploy and maintain applications tailored to your organisation.

Let's talk about your project

Comments

No comments yet: be the first to share your experience.

Leave a comment

Your first comment is reviewed before it appears. Please keep it courteous and constructive.

One email a week, zero noise

Dev, Data Science and AI insights, straight from our projects. Unsubscribe anytime.

Your data is never sold or shared. Privacy policy