Skip to content
LARAVEL11 min read

What Is a Code Audit and When Do You Need One.

ЄвгенійTech lead, 11 years in PHP / Laravel
Published
Updated

A code audit is an independent review of a project's source code, architecture and infrastructure that ends in a report: what works well, what is unsafe or slow, and in which order to fix it. You need one when you inherit a project, change contractors, prepare to scale or sell the business, or simply do not understand why every new feature costs more than the last.

Below is what we check in Laravel projects, what the report looks like, which signs show it is time to order an audit, and what you should not expect from it.

What a code audit is and what it is not

An audit is a diagnosis, not treatment. An expert reads the code, runs the project, looks at the database, dependencies, configuration and deployment process, and writes up a document with conclusions. The fixes are a separate stage that you can give to any team, not necessarily the one that performed the audit.

A code audit differs from neighboring services:

  • QA testing checks the product's behavior through the user's eyes: does the cart, the form, the payment work. That is an ecommerce QA audit. The code is not read.
  • Code review evaluates specific changes (a pull request) during development.
  • A pentest is a targeted attempt to break into the system. We do a security review at the code and configuration level, but we do not claim a full pentest.
  • A code audit covers the project as a whole: structure, quality, security, performance, processes.

The best result comes from both approaches together: QA finds the symptoms, the code audit finds the causes.

Signs that you need an audit

Not every project needs an audit every year. There are situations where it is especially justified.

  1. The team changes. A new contractor or tech lead needs to quickly understand what exactly they are getting before taking responsibility.
  2. New features get more expensive and take long. Developers say "everything is tangled up there", a classic symptom of technical debt.
  3. The site is slow or goes down under load. Especially in seasonal peaks: promotions, sales.
  4. After an incident. A data leak, an admin panel compromise, lost orders.
  5. Before major changes. Migrating to a new framework version, scaling, integrating with a CRM or 1C.
  6. Before a sale or investment. A buyer or investor wants to see the state of the asset.
  7. You do not trust the contractor's estimates. An independent opinion will help you understand whether "this really needs to be rewritten".

If at least two of these sound familiar, an audit will pay off faster than you would spend money on another round of fixes made "blindly".

What we check in a Laravel project

Architecture and code quality

The first thing we look at is where the business logic lives. In a healthy project the controller is thin: validation, a service call, a response. In an unhealthy one, the controller runs to 600 lines with discount calculation, email sending and payment provider handling.

We check:

  • separation of responsibilities: controllers, services, Form Requests, Policies, Jobs;
  • code duplication and "god" classes;
  • dependencies between modules and circular relations;
  • alignment with the framework: whether its mechanisms are bypassed with home-grown ones;
  • test coverage and reproducibility: whether tests pass and whether there is CI.

A typical example of a problem we describe in the report:

// OrderController.php — logic in the controller
public function store(Request $request)
{
    $total = 0;
    foreach ($request->items as $item) {
        $product = Product::find($item['id']);      // query in a loop
        $total += $product->price * $item['qty'];
    }
    if ($request->promo === 'SALE10') {            // "magic" value
        $total *= 0.9;
    }
    $order = Order::create([...]);
    Mail::to($request->email)->send(new OrderMail($order)); // synchronous sending
}

In the report this turns into concrete items: move the calculation into a service, load products in one query, store promo codes in the database, send the email through a queue.

Security

For Laravel we check basic but critical things that are often missed:

  • APP_DEBUG=true in production and leaked environment variables;
  • mass assignment ($guarded = []) and missing access checks in controllers;
  • SQL injection through raw queries (DB::raw, whereRaw with concatenation);
  • XSS through output of unescaped data ({!! !!});
  • file uploads without type and size checks;
  • CSRF, cookie settings, security headers;
  • outdated packages with known vulnerabilities (composer audit);
  • secrets stored in the repository and in git history.

A dangerous example that appears more often than we would like:

// admin search: injection through concatenation
$orders = DB::select("SELECT * FROM orders WHERE email = '" . $request->email . "'");

// correct: parameter binding
$orders = DB::select('SELECT * FROM orders WHERE email = ?', [$request->email]);

Separately we look at customers' personal data: what is stored, who has access, whether there are backups and logging. This is not a legal opinion but a technical risk assessment.

Performance and the database

Most slow Laravel sites suffer from a few recurring problems:

  • N+1 queries. A list of 50 products produces 150 database queries because relations are loaded one by one. It is cured with with(), but first it has to be found.
  • Missing indexes on columns used for filtering and sorting.
  • Heavy queries on every page request: counters and totals that could be cached.
  • Synchronous work with external APIs in the main flow: Nova Poshta, the payment provider, emails.
  • No caching of configuration, routes and results of expensive computations.

We turn on the query log in the test environment, walk through the key flows (catalog, product page, cart, checkout) and record the number of queries and the response time. To detect N+1, it helps a great deal to forbid lazy loading in non-production environments:

// AppServiceProvider::boot()
Model::preventLazyLoading(! app()->isProduction());

After that, any suboptimal query fails with an error already in development. In the report we show before and after in numbers, not general words about "optimization".

Database and data

We check the schema: whether it can be rebuilt from scratch by migrations, whether there are foreign keys and unique constraints, how money is stored (integers in minor units or decimal, but not float), and whether there are "junk" tables and duplicates. For a store, order statuses, stock and prices matter especially: errors here cost money.

Dependencies and maintainability

PHP version, Laravel version, support status, packages with no updates for several years. We do not advise "updating everything at once"; we build a realistic plan: what is critical (vulnerabilities), what is desirable, what can wait.

Infrastructure and deployment process

  • How is the project deployed: manually over FTP or automatically with test checks?
  • Is there a staging environment distinct from production?
  • Backups: has anyone ever restored one?
  • Error and uptime monitoring: do you learn about an outage from a system or from a customer?
  • Logs and alerts.

A backup that has never been restored is a hypothesis, not a backup. We check this first.

What the audit result looks like

A good report answers three questions: what is wrong, how critical it is and what to do first. We structure it like this:

SectionContent
Executive summary1 page for the owner: overall state and main risks
FindingsA description of where exactly in the code, why it is a problem, how to reproduce
PrioritiesCritical / serious / desirable, an assessment of impact on money and risk
Fix planSequence of work, approximate effort, dependencies
Quick winsWhat can be done in 1–2 days with a visible effect
Process recommendationsTests, CI, review, monitoring

We do not write "the code is bad" or "the code is good". Every finding is tied to a file or scenario, and the priority to its consequences: "this vulnerability lets someone view other people's orders", "this query slows the catalog down fivefold".

It is prioritization that distinguishes a useful audit from an 80-page list of remarks. A business owner is not obliged to fix everything but has to know what is on fire and what can be left.

Need an audit of your Laravel project? We review architecture, security and performance and deliver a report with a fix plan in 5–7 days. The price is from UAH 12,000; details are on the code audit page.

How much it costs and how long it takes

The cost depends on the size of the codebase, the number of integrations and the depth of review. On the pricing page a code audit of a Laravel project costs UAH 12,000–25,000 depending on scope and takes 5–7 days. We name the exact sum after a short look at the project: repository size, number of models and routes, presence of tests.

Factors that increase the scope:

  • a large number of integrations (payment, delivery, CRM, 1C);
  • no documentation or tests, so we have to figure things out "from scratch";
  • several applications (backend, Nuxt frontend, mobile client);
  • an old framework version with non-standard patches.

For a consultation without a full audit there is the Tech Lead by the hour format: 90 minutes of conversation, an architecture review and answers to specific questions.

What to prepare for an audit

To keep the audit quick and free of unnecessary pauses, provide:

  1. Read-only access to the repository (or a code archive).
  2. A copy of the database without personal data, or access to a test environment.
  3. A project description: what it does, who the users are, which scenarios matter most to the business.
  4. A list of integrations and external services.
  5. Known problems: what is slow, what breaks, what scares the developers.
  6. Infrastructure information: hosting, deployment method, monitoring.

Secrets (API keys, passwords) are not needed: we work with anonymized or test values. A non-disclosure agreement can be signed before we receive the code.

What to do with the report next

After the audit you have three paths:

  • Fix it yourself or with your current team. The report serves as the requirements.
  • Hand the fixes to us. A fix package is calculated at rates of $20–35 per hour according to the volume of findings.
  • Use the report as an argument in a conversation with a contractor or when choosing a new one. Read about that in How to Choose a Web Development Contractor.

A common mistake is trying to fix everything at once. It is better to follow priorities: first security and loss of money, then performance, then code structure. And accompany every fix with a test so as not to break neighboring functionality. If the project is critical to the business, it is useful to add automated checks: more in the article on manual vs automated testing.

How to tell a quality audit from a formal one

The audit market is uneven: from an automatic static analyzer report to a deep architecture review. A few signs will help you assess an offer.

  • Manual review, not just tools. Static analyzers (PHPStan, Larastan) and composer audit are useful, but they do not see business logic. If the whole audit is a printout of tool output, you are paying for something you could have run yourself.
  • Findings with examples. Every remark has a file, a line and an explanation of consequences. "We recommend improving security" is not a finding.
  • An effort estimate. A fix plan without approximate hours will not help you plan a budget.
  • A conversation with you, not just with the code. The auditor should ask what matters most to the business: catalog speed, payment reliability or ease of change. The priorities depend on it.
  • Honest limits. A good auditor says directly what was not checked: for example load testing or the legal compliance of personal data processing.

If an audit is offered for free "as a gift" with development, remember the conflict of interest: the one who writes the code rarely assesses their own work objectively.

Summary

A code audit is not about "finding who is to blame". It is a way to replace the feeling that "something is off" with a concrete list of problems, risks and actions. You need it when a project changes owner or team, slows down, gets more expensive to develop or prepares for growth. The result is a report that can be handed to any team and carried out in stages.

Want to understand the real state of your project? Leave a brief or write to us on the contacts page: we will look at the project and tell you whether you need a full audit or a consultation will do.

AUTHORЄвгенійFounder and tech lead of Tochno. 11 years in PHP / Laravel, dozens of online store audits. Writes about what he sees in real projects.About the team

Quick answers

Didn't find an answer? Message us on Telegram.

What is checked during a technical code audit?

Architecture, security, performance, code quality, dependencies, tests and the way the project is deployed. In a Laravel project we look at database queries, validation, access rights and error handling. The result is a report with priorities, not just a list of remarks, so the owner sees what is urgent and what can safely wait.

How much does a Laravel code audit cost?

A technical audit of a Laravel project costs UAH 12,000–25,000, depending on the size of the codebase, the number of integrations and the depth of the review. We give an exact figure after a short look at the project. Fixing the findings is paid separately at $20–35 per hour, and we agree the final cost with you before work starts.

How long does a code audit take?

Usually 5–7 days until the report with a fix plan is delivered. The timeline grows with many integrations, missing documentation and tests, several applications or an outdated framework version. We give an estimate after reviewing the project. The report orders findings by business impact, so you can decide on fixes right away.

What do I need to prepare for a code audit?

Read-only access to the repository, an anonymized copy of the database or a test environment, a description of the project and its integrations, and a list of known problems. Passwords and API keys are not needed: we work with test values. A non-disclosure agreement can be signed before you hand over any code.

Recognise your project?

Describe your task in the brief — we'll reply with an estimate and a plan within one business day.

What you need

By submitting the form you agree to the privacy policy.