Skip to content

Laravel in New York

Laravel development for New York companies

A Laravel development company working with New York teams. About an hour of overlap, and sales tax that is a per-address calculation rather than a rate on the product.

New York is about eight hours behind us. Our day ends as yours begins, so the overlap is roughly an hour, and that decides how the engagement is run before anything technical does.

New York sends proposals, not questions

With one shared hour, the difference between a project that moves and one that stalls is the form of what gets written.

A question sent at the end of our day is read at the start of yours, answered at the end of yours, and read again at the start of ours. Two days for one exchange, and often the answer raises another question.

A proposal is different. "I propose we store the tax breakdown per line rather than per order, because a partial refund has to return the right tax; proceeding unless you object by your end of day." That gets decided overnight, and the objection - if there is one - arrives with the context already shared.

It is a small habit and it roughly doubles the pace of a distributed engagement. Teams that already write decisions down barely notice the time zone; teams that decide things in meetings find this genuinely hard, which is worth knowing before signing rather than in month two.

For a New York seller, tax is a calculation rather than a rate

This is the local specific that reaches the schema, and it surprises European teams more than anything else here.

There is no national sales tax. Rates differ by state, by county, by city and by special district, they change on schedules nobody controls, and whether a given product is taxable differs too - the same item can be taxable in one jurisdiction and exempt in the next county.

So tax is a service call against a specific address at a specific moment, not a column on the product. The engineering consequence is about storage rather than calculation: what the service returned has to be recorded with the order, per line, including the jurisdiction breakdown. A return filed next quarter must reconcile against what the customer was actually charged, and recomputing it later with today's rates produces a number that is correct and useless.

Partial refunds are where this bites. Refunding half an order means returning the right tax for the half being refunded, which is only possible if the breakdown was stored per line in the first place.

Marketplaces and the money Laravel holds in the middle

A good share of New York work is a marketplace or a subscription product, which means the application holds money that belongs to somebody else for a while.

Two things matter more than the rest. A payout is not a transfer - it is a sequence of states, each of which can fail, and knowing what is owed to whom at every instant is the property that keeps it recoverable. And every step has to be safe to repeat, because the queue underneath retries by design and a payout job that is not idempotent is the one that pays somebody twice.

The same reasoning applies to the provider webhooks that drive the whole thing. They arrive late, twice and out of order, and a handler written as though they do not is the most common serious bug in this kind of system.

A New York subscription changes in the middle of a month

Upgrades do not wait for a billing anniversary. A customer moves to the next tier on the eleventh, and the invoice has to make sense to somebody in finance.

Proration is the visible part and the easy part - unused time on the old plan credited, remaining time on the new plan charged, both computed from dates rather than from a fraction somebody rounded. The harder part is that a subscription is a sequence of periods with a plan attached to each, not a row with a current plan. Once it is modelled that way, mid-cycle changes, trials, pauses and downgrades that take effect at renewal are all the same shape, and the invoice is derived from the periods rather than assembled by special cases.

Credit balances need somewhere real to live. A downgrade that produces more credit than the next invoice consumes leaves money owed to the customer, and that is a balance with a history, not a discount applied to the next charge and forgotten. It appears on a statement, it carries forward, and it has to be refundable.

The invoice itself is a document that stops changing once it is issued. The plan's price can be edited next week; the invoice that referenced it cannot move. That means the invoice stores its own line descriptions and amounts rather than resolving them through relationships at render time - the same rule as any other figure a customer has already seen.

Laravel webhooks from a payment provider arrive twice and out of order

The provider's documentation says delivery is at-least-once and ordering is not guaranteed. Both halves of that sentence will be tested in production.

Duplicates are handled by storing the event identifier with a unique constraint and treating a collision as success. The handler does not ask whether it has seen the event; the database refuses the second one. That distinction matters under retries, where two deliveries of the same event can be in flight at the same time and a check-then-act will occasionally let both through.

Ordering is the subtler problem. A subscription-updated event arriving after a subscription-cancelled event will, if applied naively, resurrect a cancelled subscription. The defence is not to trust arrival order at all - each event carries the state as of its own moment, so the handler compares the event's version or timestamp against what the record already reflects and declines to apply anything older.

Reconciliation closes the gap that webhooks always leave. Some events never arrive, and a system that only learns about payments through webhooks will drift. A scheduled job that reads the provider's own records for the period and compares them against what the application holds finds the drift while it is still small - and the provider is the source of truth about money it has collected, which means the reconciliation reports the difference rather than quietly overwriting one side with the other.

Commercially

Invoicing is from Codefacture Yazılım A.Ş., a Turkish company, in US dollars by bank transfer. The export-of-services exemption means no Turkish VAT is charged. There is no US entity on our side and no US tax filing done on your behalf, so your finance team treats this as an ordinary foreign supplier.

The state-level privacy patchwork and the rest of the country ground are on the United States market page.

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

Frequently asked questions

One hour of overlap - does that work?
It works if decisions get written down, and it fails if they do not. The practical rule is to send proposals rather than questions. "I propose X because Y, proceeding unless you object by your end of day" advances overnight; "what do you think?" costs two days and comes back with another question.
Do we need a sales tax service, or can we compute it ourselves?
Use a service. Rates vary by state, county, city and special district, they change on their own schedule, and whether a particular thing is taxable varies too. The engineering question is not the calculation - it is storing what the service returned at the moment of the sale, because a return filed next quarter has to match what the customer was charged, not what today's rate would be.
Our marketplace pays out to sellers. What should we be careful about?
That a payout is not a transfer, it is a sequence of states that can fail halfway. Hold the money, know what is owed to whom at every instant, and make every step repeatable - the queue underneath will retry, and a payout job that is not safe to run twice is the one that sends somebody two payments.
Are you a US entity, and does that matter for a New York contract?
No. Invoices come from Codefacture Yazılım A.Ş. in Türkiye, in US dollars, by bank transfer, with no Turkish VAT because exported services are exempt. Your finance team treats it as any other foreign supplier.
Call us+1 848 272 7583WhatsApp+90 850 308 5436Emailinfo@codefacture.comContact page