· frameworks · 5 min read
Unleashing the Power of AdonisJS: Top 5 Tips for New Developers
Practical, hands-on tips for developers starting with AdonisJS - learn TypeScript-first patterns, Lucid ORM best practices, validation, auth & permissions, testing, performance, and common pitfalls to avoid.

Introduction
AdonisJS is a TypeScript-first, batteries-included Node.js framework that gives you a structured, productive environment for building web apps and APIs. If you’re new to AdonisJS, you can move quickly - but there are a few patterns and pitfalls every newcomer should learn to get the most out of the framework.
This article walks through the top five practical tips for new AdonisJS developers, with examples, common mistakes, and links to the official docs so you can dig deeper.
Why AdonisJS matters for new projects
- TypeScript-first developer experience with typed models, controllers, and requests.
- Built-in pieces for common needs: routing, middleware, authentication, authorization (Bouncer), validation, ORM (Lucid), queues, caching, and testing.
- Conventions that reduce decision fatigue and speed up development.
If you already know Express or another Node framework, think of Adonis as a higher-level framework that helps keep projects consistent and maintainable.
Tip 1 - Embrace the TypeScript-first structure and the IoC container
AdonisJS is opinionated about project structure (folders like app
, start
, config
, providers
) and uses an IoC container to resolve dependencies. Learning those conventions pays off quickly.
Why it helps:
- Easy discoverability: controllers live in
app/Controllers/Http
, models inapp/Models
, middleware inapp/Middleware
. - Providers and bindings let you register and replace services without touching application code.
- Type safety reduces runtime errors and gives better IDE completion.
Quick examples:
Register middleware in
start/kernel.ts
(this is where route/global middleware is configured).Use dependency injection via the IoC container by importing with the
@ioc:
alias, e.g.:
import Database from '@ioc:Adonis/Lucid/Database';
Common mistakes to avoid:
- Bypassing the IoC container frequently (e.g., require/import hacks) - this reduces testability.
- Mutating global state in providers or models - keep services stateless or thread-safe.
Docs: https://docs.adonisjs.com
Tip 2 - Master Lucid ORM: relationships, eager loading, and transactions
Lucid is Adonis’s ORM and gives you typed models and a fluent query builder. Learn these fundamentals early:
- Models and relationships (hasMany, belongsTo, manyToMany).
- Preloading (eager loading) to avoid N+1 queries.
- Transactions for multi-step writes.
- Pagination and query scopes.
Examples:
Eager loading to avoid N+1:
// Bad (N+1): calling .related for each user
const users = await User.all();
for (const u of users) {
await u.related('posts').query(); // causes N+1 queries
}
// Good: preload posts on the initial query
const usersWithPosts = await User.query().preload('posts');
Using transactions (pattern):
import Database from '@ioc:Adonis/Lucid/Database';
const trx = await Database.transaction();
try {
// perform multiple operations that should be atomic
await user.useTransaction(trx).save();
await order.useTransaction(trx).save();
await trx.commit();
} catch (error) {
await trx.rollback();
throw error;
}
Tips:
- Use
preload()
for relations you know you’ll need; avoid over-eager preloading large collections. - Prefer database transactions for multi-step operations that must be atomic.
- Use query scopes to encapsulate frequently used query logic.
Docs: https://docs.adonisjs.com/guides/lucid
Tip 3 - Validate and sanitize early: use the Validator and request schemas
Adonis comes with a powerful validator that integrates nicely with TypeScript. Validate and sanitize input in request handlers or dedicated validator classes.
Why:
- Avoid invalid data at the boundary of your application.
- Keep controllers thin and focused on orchestration.
- Provide consistent error messages to API clients.
Example using the validator in a controller:
import { schema, rules } from '@ioc:Adonis/Core/Validator';
const registerSchema = schema.create({
email: schema.string({}, [rules.email()]),
password: schema.string({}, [rules.minLength(8)]),
fullName: schema.string.optional(),
});
// In controller action
const payload = await request.validate({ schema: registerSchema });
// payload is typed according to schema and safe to use
Best practices:
- Create dedicated validator files or classes for complex validations.
- Sanitize incoming payloads so you don’t accidentally allow untrusted fields to be mass-assigned to models.
- Return user-friendly validation errors and log server-side validation failures for debugging.
Docs: https://docs.adonisjs.com/guides/validator
Tip 4 - Use built-in Auth, Bouncer, and middleware for guardrails
Authentication and authorization are easy to get wrong. Adonis gives you:
- Auth providers (JWT, session-based, etc.).
- Bouncer for expressive authorization policies.
- Route middleware for enforcing authentication and roles.
Simple route protection:
// routes.ts
Route.get('/dashboard', 'DashboardController.index').middleware(['auth']);
Using Bouncer for authorization (concept):
// define a policy or ability in Bouncer
// then check it in a controller or middleware
await bouncer.authorize('updatePost', post);
Tips:
- Always protect sensitive routes with middleware or Bouncer checks - don’t rely only on controller logic.
- Use guards when your app needs multiple auth strategies (API tokens + session, etc.).
- Keep authorization rules in policies or Bouncer files to centralize access logic.
Docs: https://docs.adonisjs.com/guides/auth and https://docs.adonisjs.com/guides/bouncer
Tip 5 - Test early, optimize smartly, and prepare for production
Testing and performance tuning are often postponed - but small investments up front pay big dividends.
Testing:
- Use Adonis’s preferred test runner (Japa) and write unit and integration tests for controllers, models, and services.
- Mock external services and use test databases or transactions to keep tests isolated.
Performance & operations:
- Cache heavy or frequently read queries with Redis (e.g., query results, computed counters).
- Push long-running work to a queue/worker instead of blocking requests.
- Monitor DB queries for slow statements and use indexes where appropriate.
- Use connection pooling and graceful shutdown to avoid dropped requests during deploys.
Deployment checklist:
- Never store secrets in source - use environment variables and a secrets manager.
- Configure CORS and security headers.
- Use a process manager like PM2, Docker, or a platform provider; enable zero-downtime deploys where possible.
Docs & tools:
- Tests: https://japa.dev
- Queues and workers patterns: https://docs.adonisjs.com/guides/queues
Common pitfalls and how to avoid them
- Over-eager preloading: preload only what you need to avoid memory/DB blowups.
- Ignoring TypeScript types: embrace typed contracts for controllers, models, and services to catch bugs early.
- Not using transactions: for multi-step updates, always use transactions to prevent partial writes.
- Exposing raw SQL or interpolated queries - prefer parameterized queries and the query builder to avoid injection.
- Not sanitizing input or mass-assigning model attributes - explicitly pick fields to assign or use model hooks carefully.
Quick actionable checklist for your first AdonisJS projects
- Use TypeScript and learn the project layout (app, start, providers, config).
- Write request validators and sanitize inputs.
- Learn Lucid relationships, use
preload()
and transactions. - Protect routes with
auth
middleware and centralize authorization with Bouncer. - Write tests (unit + integration) early with Japa.
- Add caching/queues for expensive or asynchronous tasks.
- Use environment variables for secrets and set up monitoring/logging.
Further reading and references
- Official AdonisJS docs: https://docs.adonisjs.com
- Lucid ORM guide: https://docs.adonisjs.com/guides/lucid
- Validator guide: https://docs.adonisjs.com/guides/validator
- Auth guide: https://docs.adonisjs.com/guides/auth
- Bouncer (authorization): https://docs.adonisjs.com/guides/bouncer
- Japa test runner: https://japa.dev
Summary
AdonisJS helps you build maintainable, well-structured Node.js applications quickly. For new developers: learn the conventions, embrace TypeScript, master Lucid, validate inputs, centralize auth/authorization, and invest in tests and production readiness. Follow these tips and you’ll avoid common mistakes while maximizing Adonis’s productivity advantages.