Skip to content

Service

APIs and backends with Laravel

A backend serving several front ends needs clear contracts and must not hang off session storage. We lay it out that way from the first day.

One backend, several front ends

As soon as an application has more than one way in, the centre of gravity moves. A web interface, an app, perhaps a partner system as well. The business rules then belong in exactly one place, and every way in asks the same interface. Otherwise each channel grows its own set of special cases, and what is true about a record depends on who is asking.

Laravel brings the parts for this arrangement with it. Output is shaped by a resource, validation sits in the request, long-running work goes into jobs, clients sign in with a token. That is how we built the backend behind the fishing guide apps, for example.

Why stateless

A backend that holds no session data in the process can run any number of times in parallel. If one instance fails, the next takes over and nobody notices. If load grows, instances are added. This is not a question of size, by the way. A small application benefits too, because a restart after deployment then no longer throws anyone out of their session.

It is paid for in discipline. Anything that has to survive between two calls belongs in the database or in a shared cache. Not in the memory of the process, and not “just for the test either”. Hold to that and you save yourself the rebuild later.

Integration work: ERP, inventory and other systems

Most often our projects are not about a new app at all, but about the connection to something that has been there for years. An ERP, an inventory system, a payment provider.

An ERP integration is rarely a technical problem. The question that costs time is a business one: which system owns a record, and what happens when both sides change it at the same time? Decide that too late and you end up with two truths, and you notice at stocktaking. So we settle ownership explicitly, field by field where necessary, before the first line of transfer code exists. Beyond that we work to a plain rule. The other system is unreliable until proven otherwise. Every call gets a timeout, every transfer a way to retry, every failure a trace you can still read three weeks later. What that looks like is visible in the travel portal under our work, which reconciles more than 150,000 places to stay every day.

More on how we take over existing systems is under migration and upgrades.

Architecture diagram in three columns: on the left the entry points web interface, mobile app and partner system, in the middle a load balancer in front of three identical Laravel instances, on the right the shared database, a cache and a file store.
A stateless backend: the instances hold nothing in the process, share database, cache and file store, and can therefore be multiplied rather than enlarged. If one fails, the next one takes over.

In detail

What a dependable API is made of

  • Stateless from the start

    No state in the server process. That way the backend can be rolled out several times behind a load balancer without sessions going missing.

  • A clear contract

    Fixed shapes for requests and answers, versioned. Whoever uses the API has to be able to rely on nothing shifting underneath them.

  • Authentication

    Tokens for machines, sessions for browser front ends on the same domain. Which one fits is decided by the use case.

  • Queues

    Sending mail, exports, calls to other systems. Whatever takes time moves into a job. The answer stays quick, however much runs behind it.

  • Errors and limits

    Error codes that say something, a capped call rate, sensible timeouts. An API that simply hangs under load is worse than one that refuses clearly.

  • Documentation

    A description another team can connect against without asking. Generated from the code, so that it does not go stale.

More services

You may also need

FAQ

Questions about interfaces

REST or GraphQL?
REST in most cases, because it is simpler to run, to cache and to debug. GraphQL earns its keep where a great many different clients need very different slices of the same data. That is rarer than the debate suggests.
Can you connect our existing front end?
Yes. Whether it is Vue, React, Angular or a native app makes no difference to the backend, as long as the contract holds. Where a front end already exists, we shape the API around it instead of pushing a rebuild on you.
How do you keep the API stable when something changes?
Changes that would break existing clients get a new version. The old one stays reachable for as long as it is needed. Anything that can be added without breaking, we add to the version already running.
What about very heavy load?
A stateless backend can be multiplied sideways, and that is the biggest lever. On top of that come caches for expensive queries and queues for everything that need not happen at once. Where the limit sits depends on your data, so we measure it rather than assert it.

Need a backend for several channels?

Tell us which clients are meant to reach it. The shape of the interface follows from that.