Skip to content

Laravel in Hamburg

Laravel development for Hamburg logistics and publishing

A Laravel development company for Hamburg freight and publishing firms. EDI messages that arrive twice and out of order, nightly imports of hundreds of thousands of rows, and rates that change by date

Hamburg's two large industries ask a backend for the same uncomfortable thing: be correct about data you did not produce and cannot correct at the source.

Freight forwarders, shipping lines and port logistics operators sit downstream of terminal systems, customs platforms and partner EDI feeds. Publishers sit downstream of wires, syndication and an archive that predates every system currently running. Neither can fix the upstream, so the application has to absorb the mess without passing it on.

Hamburg EDI messages repeat, arrive late, and arrive out of order

This is the defining property of logistics integration and the source of most of its bugs.

A partner sends a status message twice because their retry fired. A customs update for Tuesday arrives after the one for Wednesday. A correction arrives for a consignment that the system has already closed. None of these are exceptional and an application that treats them as exceptional will produce wrong totals quietly for months.

What works is unexciting. The sender's reference becomes a unique constraint, so a duplicate is rejected by the database rather than by a check somebody might remove. Events carry the time they happened as well as the time they arrived, so ordering is a property of the data rather than of the delivery. And the raw payload is stored before parsing, which is what settles the eventual disagreement about whose system was wrong.

Laravel's queue retries by design, which is a feature here and a trap if the job was never written to be safe to run twice.

The nightly Laravel batch is a reliability problem, not a speed problem

Every Hamburg logistics system has an import that runs at three in the morning and everybody is slightly afraid of.

Making it faster is mostly mechanical - insert in chunks rather than instantiating a model per row, stop querying inside the loop, and let the database do the aggregation it is better at. That work is covered under database and Eloquent engineering and it is the half that gets attention.

The half that matters more is what happens when it dies at row 240,000. If the job cannot say what it has already processed, the operator has two bad options and no good one. So the import records progress as it goes, and a restart resumes - which also means the job can be deliberately stopped, which turns a six-hour commitment into something you can interrupt.

Hamburg freight rates are true on a date

Reference data in this industry is not a lookup table. It is a history.

A freight rate, a surcharge, a port tariff, a currency conversion - each was true for a period and then was replaced. If the row is updated in place, the system loses the ability to explain a charge from three months ago, and in a dispute with a customer that is the only thing anybody wants.

The fix is a validity period on the reference row and a stored reference to the version actually used on the charge. It is slightly more schema and it is the difference between an invoice you can defend and one you can only apologise for. The same reasoning applies to money and dates generally, which are the two things in a logistics system that cannot be fixed afterwards.

A Hamburg title exists before it is published, and that is a lifecycle

In publishing, a product has an identity, a catalogue entry and a sales history before anything has been printed, and the system has to describe something that does not yet exist.

A title is announced with a provisional publication date, a provisional price and metadata that is incomplete by design. Retailers take that feed, list the product, and accept pre-orders. Then the date moves, which it does, and everything downstream has to be told. Modelling the publication date as a single field that somebody edits loses the fact that it moved, and the publication date having moved is precisely what a retailer's system needs to know.

Editions and formats are where the hierarchy gets decided. One work, several editions, each with its own identifier, price, territory rights and availability. Hardback available everywhere, paperback not yet, audio in two territories only, ebook excluded from one because the rights were sold separately. A flat product table cannot express that, and the rights dimension is the one that causes real trouble when it is missing - a product offered where it may not be sold is a contractual problem, not a display bug.

The metadata feed is an obligation with a format. Retailers consume a structured record and reject what does not conform, so the catalogue has to be able to produce a valid record per edition per territory, and know which retailer has been sent which version. That last part is what makes "why is the price wrong on that site" answerable.

Laravel royalty statements for a Hamburg publisher

Royalties are the calculation that teaches a team why versioned reference data matters, usually the hard way.

Sales arrive from a dozen channels at different granularities and on different schedules - some per transaction, some as a monthly summary, some net of returns and some gross. Normalising that into a single sales ledger, with the source and its granularity recorded, is most of the work. A summary that cannot be decomposed is still usable, provided the system knows it is a summary and does not later attempt to attribute it to a territory it never specified.

Returns arrive late, which is the structural problem. A statement for the first half of the year is issued, and returns against those sales keep coming for months afterwards. Reserves against returns are how the trade handles it - a proportion withheld, released later - and that is a balance with a policy attached rather than an adjustment somebody makes by hand.

Rates escalate on cumulative sales, which means a rate depends on the history and not just on the period. Ten per cent to five thousand copies, twelve and a half after that, counted across the life of the edition. Compute that from the period alone and the answer is wrong for every author who crossed a threshold. Compute it from cumulative units with the threshold state stored per edition and the statement is reproducible, which is the requirement - because an author is entitled to understand their statement, and a figure nobody can explain is a dispute waiting to happen.

Commercially

Scope fixed in writing before work starts, priced per project. The country-level ground - German data protection obligations on a supplier, the e-invoicing format, hosting - is on the Germany market page.

Invoiced by Codefacture Yazılım A.Ş. in Türkiye, in euros, by bank transfer to an IBAN, with no Turkish VAT under the export-of-services exemption.

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

Frequently asked questions

Our partners send EDI messages and some arrive twice. How should a Hamburg freight system handle that?
Treat the message reference as the primary key of the fact rather than as a field on it. A unique constraint on the sender and their reference turns a duplicate into a no-op at the database level, which is the only place the guarantee actually holds. Then record the raw message before parsing it, because the first argument about whose data was wrong is settled by the original payload and not by your interpretation of it.
A nightly import of 400,000 rows takes six hours and sometimes dies.
Two separate problems, and the second matters more. Speed usually comes from chunked inserts instead of a model instance per row, and from not loading a relationship inside the loop. Resumability comes from design - the job records what it has processed, so a restart continues rather than starting again or double-counting. A six-hour import that cannot resume is a six-hour outage every time something upstream hiccups.
Freight rates changed in April. Why can we no longer reproduce a March invoice?
Because the rate row was updated rather than superseded. Reference data in logistics is effective-dated by nature, so the table needs a validity period and the charge needs to record which version it used. Overwriting is the single most common cause of a historical figure that cannot be explained, and it is unrecoverable once the old value is gone.
Our editors outnumber our developers. Does that change the build?
It changes what gets built first. A publishing operation where twenty editors depend on two developers needs scheduling, embargoes and corrections to be ordinary editorial actions rather than deployments. The useful test is whether an article can be pulled at 23:00 by somebody who cannot deploy, and whether a scheduled piece still publishes if the queue worker restarted an hour earlier.
Call us+1 848 272 7583WhatsApp+90 850 308 5436Emailinfo@codefacture.comContact page