Skip to content

Laravel in Berlin

Laravel development for Berlin teams

Laravel and PHP engineering for Berlin product teams - an hour of time difference, your own engineers in the pull requests, and deletion and export duties that land in the schema.

A Berlin product company usually has engineers before it has a backend problem, and that ordering decides what an engagement here looks like. Nobody is buying a specification taken away and returned in three months, because there is already a team who would have to live with the result.

What arrives instead is a named problem - a queue that loses jobs, a schema that stopped describing the business, an authorisation rule that only holds in the controller - and a request to fix it in the repository where it lives.

Seven hours of overlap with Berlin

Berlin is one hour behind Ankara. There is no part of your working day we are not reachable for, which matters most for the work that genuinely cannot be done asynchronously.

A migration against a forty-million-row table is agreed on a call and watched by both sides. A worker that starts behaving differently after a deploy gets diagnosed while somebody who knows what the data means is still at their desk. With six to eight hours of difference each of those becomes a next-day item, and a backend fault that waits a day usually costs more than the repair.

What a Berlin codebase usually needs

The gaps that recur in Berlin codebases are consistent enough to name.

The queue is the most common. Jobs that are not safe to run twice, in a system that retries by design - which means there is already a duplicate email, a duplicate charge or a duplicate webhook somewhere that nobody has traced.

Next is the schema that described the business two pivots ago. Columns nobody writes to, a status enum with values that mean different things depending on when the row was created, and a JSON column that became the place new fields go because adding a migration felt heavy. Each addition was reasonable; the sum is a model nobody can reason about.

Third is authorisation applied in controllers rather than at the data. It works until something reaches the records by another path - an export, a scheduled report, an internal tool - and those are exactly the paths that leak. Authorisation is not authentication, and the difference shows the first time an endpoint is called directly.

Data protection is a Laravel schema decision

The German obligations that matter to a backend are not the ones on the privacy page.

Deletion has to delete. A deleted_at column is a filter, and the row remains readable by anything that forgets the scope. It is also rarely the only copy - the same personal data sits in the search index, in an analytics export, in last night's backup and in a CSV somebody generated for a meeting.

Export has to be assemblable. Producing everything held about one person is only possible if you know where it all lives, which is a question about the data model rather than about a form.

And consent is a record with a version and a timestamp, not a boolean. The question asked later is never "did they agree" but "to what, and when, and under which wording".

None of these are difficult to build at the start. All are expensive once there are three years of rows.

In Berlin the works council has a say in what the system records

An internal tool that touches how people work is not purely a technical decision in Germany. Where a works council exists, a system capable of monitoring staff performance or conduct is subject to co-determination, and that is not a formality to be settled after launch.

The practical consequence is that what the application records about its own users becomes an explicit design question rather than a side effect. A timestamp on every action, a log of who viewed which screen, a dashboard showing throughput per person - each of those may be perfectly reasonable and each has to be justified, bounded and agreed rather than built because it was easy.

What that looks like in the schema is narrower logging with a stated purpose and a retention period, aggregates where individual attribution is not needed, and the ability to switch a particular collection off without unpicking the application. A system designed on the assumption that everything is logged forever cannot be adjusted when the agreement says otherwise; one where each collection is a deliberate, separable decision can.

Engaging early is cheaper, and this is the part worth saying plainly to a project sponsor. A feature built, demonstrated and then withdrawn because the council objected costs the build twice. The same conversation held while the feature is a paragraph costs nothing.

A Berlin application that got slow gradually

Nothing broke. The application is simply slower than it was eighteen months ago, and nobody can point at the change that did it, because there was no change - there was growth.

The diagnosis has an order and skipping it wastes weeks. Measure first, in production, with per-query timing and a view of what the slowest requests actually spend their time on. The intuition about which page is slow is right about half the time, and the cause is almost never where the team expected.

What it usually is, in a Laravel application of that age, is a list view issuing one query per row. It was invisible at a thousand rows and is fatal at four hundred thousand, and it is produced by exactly the convenience that makes Eloquent pleasant to write. Eager loading fixes it in an afternoon once it has been found, and finding it reliably means a tool that flags the pattern in tests rather than a developer noticing.

Second most common is an index that was never added, because the query was fast on the development machine's dataset. Third is a count query on a table that has grown past the point where counting is cheap, run on every page load to render a pagination control nobody uses.

None of that is a rewrite, and the instinct to treat gradual slowness as evidence that the architecture is wrong is expensive and usually mistaken. The measurement is what distinguishes the two, and it costs a day.

Working alongside the engineers who inherit it

A buyer with a team rules out the arrangement most agencies sell: a parallel repository, a parallel process, and a handover event at the end of it.

What replaces it is unremarkable, and that is the point. Your branch policy. Your review process. Your CI. Your engineers disagreeing with our pull requests in week one, while disagreement is still cheap.

Month one is slower that way. It is also the only version where the queue we fixed is still working a year later, because the people maintaining it watched it being built.

The country-level ground - the e-invoicing format, hosting decisions, what German data protection expects of a supplier - sits on the Germany market page.

The regulatory and commercial ground for this city is on the Germany market page.

Frequently asked questions

Do you work in German?
The engineering runs in English - standups, pull request descriptions, the architecture notes. German is where it has to be, which is the application's own interface and this page. A team that would rather have its backend reviewed in German should say so in week zero rather than month three; we would be the wrong supplier, and that is cheap to establish early and expensive to discover late.
Can you join our team rather than take a project?
Most of the time it is the only shape that fits. The engineers are already there; what is missing is somebody who has seen this particular failure before. We take a branch in your repository, open pull requests your people review, and leave the architectural reasoning written down where your team will find it rather than in a handover deck.
What does GDPR actually change in the code?
Three things, mostly in the schema. Deletion that really deletes rather than setting a flag. Export that can assemble everything held about one person, which means knowing where the copies are. And consent recorded with its version and timestamp, because "they agreed" is not an answer without saying to what.
Do you invoice in euros?
Yes, from Codefacture Yazılım A.Ş. in Türkiye, by bank transfer to an IBAN, with no Turkish VAT under the export-of-services exemption.
Call us+1 848 272 7583WhatsApp+90 850 308 5436Emailinfo@codefacture.comContact page