Comparing Laravel and AdonisJs – Part 1

I looked back at my git history today and worked out I’ve been using Laravel since November 2015. At the time it was like a breath of fresh air. For the 4 years leading up to that I’d been responsible for a legacy PHP application written in Symfony 1. Whilst a game changer in it’s own right the world had moved on since Symfony 1 was released and Laravel was right at the forefront of that movement. Laravel made me more productive and more confident in my code and I’ve built many apps and api’s on top of it since.

Fast forward to 2020 and I’ve been looking into Javascript more and more. The benefits of using the same language on the front and back end make sense to me. I set out to find a Javascript Framework that could replace my beloved Laravel. The first framework I found was Sails. Whilst it seems popular and robust I was struggling to get my head round a different way of planning and building apps. That’s when I discovered AdonisJs. The article that brought it to my attention highlighted how similar it was to Laravel so I had to give it a try.

This article is aimed at Laravel Developers and focuses on the similarities and differences between the two frameworks. I will focus on the key parts of the Laravel Framework that make it so productive.

  • Command Line Tool
  • Routing
  • Migrations
  • ORM
  • Testing
  • Queuing
  • Cache


One of the great things with Laravel is the ‘artisan’ cli it comes bundled with that gives loads of command line tools for doing common tasks. I’ve broken out the main sections to make the comparison easier. Both frameworks have almost identical ways to make commands, controllers, exceptions, models, providers and seeders.


  make:command         Create a new Artisan command
  make:controller      Create a new controller class
  make:exception       Create a new custom exception class
  make:migration       Create a new migration file
  make:model           Create a new Eloquent model class
  make:provider        Create a new service provider class
  make:seeder          Create a new seeder class


  make:command         Make a new ace command
  make:controller      Make a new HTTP or Websocket channel controller
  make:exception       Make a new exception
  make:migration       Create a new migration file
  make:model           Make a new lucid model
  make:provider        Make a new provider
  make:seed            Create a database seeder

They also have very similar tools for running, rolling back and resetting migrations.

The big gap that I can see in the AdonisJs CLI is commands for managing Queues. More on this later.


Routing feels almost identical. Both frameworks offer ways to respond to all the HTTP verbs, GET, POST, PUT, PATCH and DELETE. You can write your closure in the route file itself or point to a Controller.


Route::get('/', function () {
    return 'Hello World';

Route::get('/user', 'UserController@index');


Route.get('/', () => 'Hello World')

Route.get('user', 'UserController.index')


One of the most powerful features in Laravel is the ability to write all your database changes as ‘migrations’. These are files which describe the database change you are making. You run them with the CLI and Laravel keeps track of where the app is up to. It’s incredibly powerful not least because your database changes are kept in version control.

Both frameworks operate in very similar ways. Each migration has an ‘up’ and a ‘down’ method. The ‘down’ is designed to reverse the changes of the ‘up’. I’ll show a comparison of a migration designed to add a new table called airlines and add a email column to the users table.

Laravel Up:

public function up()
  Schema::create('airlines', function (Blueprint $table) {

  Schema::table('users', function (Blueprint $table) {

AdonisJs Up:

up () {
  this.create('airlines', (table) => {

  this.alter('users', (table) => {

Laravel Down:

public function down()

    Schema::table('users', function (Blueprint $table) {


AdonisJs Down:

down () {
  this.alter('users', (table) => {


As you can see they look very similar and are conceptually identical.


That concludes todays article. I’ll conclude the comparison tomorrow looking at ORM, Testing, Queues and Caching.