Skip to content

Web application development

Laravel Application Development

New Laravel applications built to survive their own success - a schema designed before the data arrives, queues you can leave alone, and a second year cheaper than the first.

Laravel makes the first three months easy, and that is the problem. The framework will happily let you ship an application whose schema was invented one migration at a time, whose jobs assume they will only ever run once, and whose slowest query is fast because the table has four hundred rows in it.

None of that is visible at launch. All of it is visible at scale, and by then the data is in production and the fixes are outages.

What we build

Applications where the behaviour is the hard part: multi-tenant SaaS platforms, marketplaces with money moving through them, internal systems that replace a decade of spreadsheets, and back offices that a business actually runs on.

Where a problem has a shape of its own it has its own page - the database when the data model is the difficulty, queues when the work happens outside the request, and APIs when somebody else has to consume it. This page is the work those share.

The schema is decided before the code

Most Laravel applications get their database by accident. A model is created, a migration follows it, a relationship is added when a screen needs one, and eighteen months later there are four columns holding a status and no two of them agree.

We design it first, on paper, and it is the part of the engagement we are most opinionated about:

  • Constraints in the database, not only in the application. A foreign key the schema enforces is a bug that cannot reach production. A rule that lives only in a form request is a rule that a queued job, an artisan command or a future developer will route around without knowing it existed.
  • Indexes chosen from the queries, not guessed. Written when the query is written, while the reason is still in somebody's head.
  • Migrations that are safe on a live table. Adding a column is free; adding one with a default, or an index, is a lock, and on a table with millions of rows a lock is an outage with a deploy attached to it.
  • Money and time stored properly. Integer minor units, explicit currency, UTC, and a decision about timezone display written down once rather than argued about per screen.

Eloquent, used deliberately

Eloquent is productive and it hides the cost of what it does, which is a fine trade until the day it is not.

We treat the query count as a number somebody owns. Relations are eager-loaded because the code says so, not because a page felt slow once. Lazy loading is disabled outright in non-production environments, so an accidental N+1 is a failing test rather than a support ticket. Aggregates that belong in SQL stay in SQL instead of being collected into memory and counted in PHP.

None of that is exotic. It is the difference between an application that degrades gracefully and one that falls over on the day the marketing worked.

Work that happens outside the request

Anything slow, anything third-party and anything that can fail belongs in a job rather than in a controller. That is easy to say and it has consequences worth designing for rather than discovering:

Jobs are written to be safe to run twice, because at some point every one of them will be. A retry is not a failure mode, it is the normal case, and a job that charges a card or sends an email has to know that. Failures land somewhere a human can see them. Long-running work is chunked so a deploy does not kill it halfway.

Testing, in the amount that pays for itself

Feature tests over the routes that matter, unit tests where the logic is genuinely intricate, and a factory for every model so that writing the next test is cheap. Not one hundred percent coverage, which buys the wrong thing at a high price.

The measure we use is whether the suite would catch the change that breaks the business. A test that asserts a controller returns 200 catches almost nothing; a test that asserts an order cannot be paid twice catches the thing that would have cost you a refund and a reputation.

The shape of the work

Four phases. Each one finishes with something running on a URL rather than something described in a status report.

  1. Scope and schema. The domain written out, the tables and the constraints that hold them together, every system this has to talk to, and the list of jobs that will exist. Everything after this is priced against what comes out of it, which is why it produces a document and not a deck.
  2. The spine. Migrations, models, authentication, authorisation, the queue layout, the deploy pipeline, and a test suite running in CI from the first commit. Nothing looks finished. Everything underneath is.
  3. Domains, highest value first. Written to the conventions phase two settled, put through your review process if you have engineers, and released at the close of each iteration rather than piled up behind a launch date.
  4. Hardening and handover. Load testing where the numbers matter, a runbook for the calls that come at three in the morning, the schema written down, and a session per domain with the people who will own it.

All of it happens where your team already works - your repository, your tracker, your reviews. Code that stays inside our tooling until launch day is code your team first sees on the day it is too late to argue with.

What actually moves the number

The framework does not. The things that decide how long a Laravel build takes are the same things that decide how long any build takes, and being told which ones apply to you is more useful than a day rate:

  • How many systems it has to talk to. One payment provider is a week. A payment provider, an ERP, a shipping API and a bank file format that is documented in a PDF from 2011 is a different project.
  • Whether the rules are written down anywhere. Building against a process that only exists in one person's head is the most reliable way to build the same screen three times.
  • Whether anything is already in production. Data that exists has to be migrated, and migrating data nobody has validated is where schedules go.
  • How much of it is reporting. Reporting looks cheap and is not: it is where the query work, the date arithmetic and the "but finance counts it differently" conversations live.

When this is the wrong engagement

If an application already exists and the problem is that it has become difficult to change or is several versions behind, that is upgrades and rescue, and it starts by reading rather than writing.

If it works but falls over under load, that is performance and scaling.

And when you genuinely cannot tell which of the two you are looking at, that is what the audit is for - two weeks, a fixed price, and considerably cheaper than committing a quarter to the wrong one.

What you receive

The application, and the four documents that make it somebody else's to run: the schema with the reasoning behind every decision that was not obvious, the queue topology and what each worker is allowed to do, the deployment runbook, and the test suite with a note on what it deliberately does not cover.

Pull requests are reviewable and land continuously, so you read the work while it happens instead of receiving it at the end. If your team is going to take it over, they should be reviewing it before that day rather than after.

Scope and terms

Engagement model
Fixed scope, agreed in writing before work starts. Not a day rate against an open backlog.
Price and timeline
Both are set per project, once the scope is. Quoted together, before anything is built.
What we need from you
One person who can approve decisions, and access to your repository and issue tracker.
Not included
Anything outside the agreed scope. It becomes its own scope rather than a variation order.
Third-party costs
Hosting, licences, API fees and SaaS subscriptions are contracted and paid by you.
Invoicing
Codefacture Yazılım A.Ş., Türkiye. EUR, USD or GBP by bank transfer, with no Turkish VAT on exported services.

Frequently asked questions

Which Laravel version do you build on?
The current release, on every new build. We maintain and upgrade older applications, but we do not start a new project on a version that is already out of active support - the upgrade you avoid today is the one that costs four times as much in two years.
How long does a typical build take?
Nobody can answer that honestly before reading the brief, and a number offered at that stage is a sales figure rather than an estimate. What stretches a schedule is never the framework - it is the length of the integration list, whether the rules are written down anywhere, and how much of the work turns out to be reporting. Scoping comes first and produces a document; every phase after it is priced against that document and ends with something deployed.
Who owns the code?
You do - from the first commit, not from the final invoice. Where the repository is ours during the build, what transfers at the end is the repository itself rather than a zip of the last state, history and branches included.
Do you build the frontend as well?
We build what the application needs: Blade with Livewire for most admin and internal surfaces, Inertia where the interaction is heavy enough to want a component framework, and a documented API where you have a separate frontend team. What we do not do is take frontend-only work with no backend in it.
What happens when the engagement ends?
You get the repository, the schema documentation, the deployment runbook, the test suite, and a handover session per domain. Continuing with us afterwards is a contract you sign on its own merits, at a point where walking away costs you nothing - which is the only condition under which that decision means anything.
Can you take over a build that is already half finished?
Often, yes - but that is upgrades and rescue rather than this, and it starts with reading the codebase rather than writing in it. The map that produces is yours whether or not the work continues with us.
Call us+1 848 272 7583WhatsApp+90 850 308 5436Emailinfo@codefacture.comContact page