Ecommerce
A store that still balances on a bad network day
You get a system where a retried payment does not charge twice and stock counts survive a race. Every order reconciles against what the processor actually settled.
Anybody can put a cart on a page. The work that decides whether your finance team trusts the system happens in the seconds after a customer's connection drops mid-payment. Did the charge land? Did the order get written twice? Does your stock count still match the shelf? Those questions have engineering answers, and they have to be built in before launch rather than patched in after the first bad month. That is the part we are hired for.
The double charge nobody can explain
A customer taps pay. The connection stalls. They tap again. Now your processor has two authorisations, your database has two orders, and your support inbox has one very annoyed person.
That retry was correct behaviour. Your system treated the second request as new information, and that is the bug. Stripe's own guidance is to retry a request whose result you never saw, using the same idempotency key. The platform then returns the original outcome instead of doing the work twice.
The same shape of failure hits inventory. Two customers buy the last unit within the same second. Both get a confirmation. One of them is going to get an apology email, and your stock figure was wrong from that moment onward.
When to build, and when to use a platform
Most stores should not be custom, and we will say so early. Selling physical products through a fairly standard flow? A hosted platform hands you a checkout that already survived millions of edge cases. You would otherwise meet those personally.
Custom earns its place when the commerce is unusual. Money held between two parties until work is done. Pricing that depends on a calculation rather than a table. Inventory that lives in somebody else's system. Subscriptions with rules your platform's billing cannot express.
If your answer is Shopify, our Shopify development page covers that work specifically, including where we extend a store rather than replace it.
- 01Standard catalogue, standard checkout: use a platform, and we will help you extend it.
- 02Money held, split or released against a milestone: that is custom, and it is where we are useful.
- 03Price computed per customer, per site or per contract: custom.
- 04Stock that lives in an ERP or a warehouse system: integration work, not a storefront project.
What is running now
Counted, not estimated
22
production systems we have shipped and can name
7
payment and billing integrations across those builds
24h
window Stripe documents for retrying with the same idempotency key
255
character limit Stripe sets on an idempotency key
What we build into a commerce system
The storefront is the part you see. These are the parts that decide whether the numbers hold.
Idempotent writes on every payment and order path, so a retried request returns the first result instead of creating a second charge.
Money stored as integers in the smallest currency unit, because a float cannot hold ten pence exactly and the error compounds across a ledger.
Stock decrements that cannot be won twice, handled in the database rather than in application code that hopes for the best.
Webhook handling that assumes duplicates and out-of-order delivery, since every payment processor will send both eventually.
A reconciliation view that matches your orders against what the processor actually settled, so a mismatch is visible the next morning.
Refunds, partial refunds and disputes treated as first-class flows rather than something support does by hand in a dashboard.
What we will talk you out of
- A custom checkout, where a hosted one keeps you further away from card data and handles more edge cases than we could justify rebuilding.
- Replatforming before anyone has established which of your current problems are actually the platform's fault.
- Reserve stockDecided in the database, not in a race.
- Take paymentIdempotency key on every attempt.
- Write the orderOnce, whatever the network did.
- Absorb webhooksDuplicates and out-of-order, expected.
- ReconcileYour ledger against the processor's.
- Handle the exceptionRefunds and disputes as real flows.
The fourth station is where most builds are optimistic. A processor may send the same event twice, and a handler that assumes exactly-once delivery will eventually ship the same order twice.
Holding money between two strangers
Marketplaces are where commerce gets genuinely difficult. The buyer has paid, the seller has not finished, and your platform is sitting on money that belongs to neither of them yet.
WorkMateAI is that shape. For Australia's on-demand trades marketplace we built hold-and-release payments on Stripe Connect. Around it sit provider verification, e-signed agreements and a dispute process that escalates in stages. Every dispute action is audit-logged, because the argument you cannot reconstruct is the one that costs you.
- Funds release against a defined event, not against somebody remembering.
- Every state change on an order is recorded, so a dispute is checked rather than argued.
- Legal documents are stored encrypted with retention rules written down.
- Admin actions are role-limited, because a support tool with full payment rights is a liability.

What we build on
Payments
Build
Commerce integrations
Run
Systems where money had to reconcile
WorkMateAI
Dispute resolution, payments, and compliance for Australia's on-demand trades.
Read the case study →
TomoDomo
Coliving operations platform for TomoDomo, Switzerland.
Read the case study →
Maidily
Integrated operations platform for residential cleaning businesses.
Read the case study →
Golancer
Freelancer operations and AI management built on Bubble.
Read the case study →
“I am extremely happy with the results and would highly recommend Hashlogics to anyone.”
Daniel Khin · CEO, PremiumAudit.io
The usual ecommerce build against ours
Both look the same on a good day. They separate on the day the network does not cooperate.
| Criterion | The usual approach | How we build |
|---|---|---|
| A retried payment | Two charges, and a support ticket. | Same idempotency key returns the first result. |
| Storing money | A float, because the column accepted it. | Integers in the smallest unit, so nothing drifts. |
| The last unit in stock | Two customers, one apology. | The database decides, and only one wins. |
| Duplicate webhooks | Processed twice, silently. | Expected, deduplicated, and safe to replay. |
| Finance asking about a gap | Someone exports two spreadsheets. | A reconciliation view built for exactly that question. |
| After launch | The contract ends at go-live. | An agreed service level, or a documented handover to your team. |
01How do you stop a customer being charged twice?
Every payment request carries an idempotency key, so a retry returns the original result rather than starting a new charge. Stripe documents a 24-hour window for safely retrying with the same key. Reuse that key with different parameters and Stripe returns an error rather than a surprise. The application also has to be built so nothing downstream of the payment runs twice.
02Should we build custom or use Shopify?
Use a platform unless your commerce is genuinely unusual, and we will tell you which you are in the first conversation. Held funds, computed pricing, external inventory and unusual subscription rules are the four reasons custom tends to win. Our Shopify page covers the extend-a-store route in detail.
03Can you work with the store we already run?
Yes, and that is most of this work. Maidily connects to Stripe, Square, QuickBooks and storefronts on Shopify, WordPress, Wix and Squarespace. A cleaning company's site was never going to be rebuilt to suit us. Integration is usually cheaper and less disruptive than replacement.
04What about PCI compliance?
We keep card data out of your systems wherever possible, which is the design decision that does most of the work. Using a hosted payment field means the card number never touches your server, and that changes which PCI questionnaire applies to you. We design to keep your scope as small as it can be, and document it for your assessor.
05Our stock counts drift. Is that fixable?
Usually, and the cause is normally that two things can decrement stock at once without either knowing. The fix is making the database the arbiter rather than application code, plus a reconciliation job that compares system stock against reality on a schedule. Where stock lives in an ERP, the honest answer is that one system must own the truth and the other must follow.
06How do you handle refunds and disputes?
As designed flows with their own states and their own audit trail, not as something support improvises in a processor dashboard. WorkMateAI escalates disputes in stages and logs every action taken. A dispute you cannot reconstruct six months later is the one that becomes expensive.
07We are a small brand. Is this overkill?
The payment correctness work is not optional at any size, and it is cheap when built in and expensive when retrofitted. What scales down is scope: one clean checkout path and one reconciliation view beats a platform you will not use. Enterprise buyers get the same foundations plus access control, audit expectations and integration into finance systems.
08What does an ecommerce build cost?
The drivers are how many systems must agree about an order, whether money is held or split, and how unusual your pricing is. Scoping conversations cost nothing. Where we have to go inside an existing codebase to answer honestly, a paid two-week diagnostic comes first.
Related
- Shopify development →Extending a store rather than replacing it.
- Why you never use floats for money →The rounding bug that compounds across a ledger.
- Idempotency key →How a retried payment avoids a second charge.
- What PCI scope actually means →Which questionnaire applies, and why the answer changes.
- API integration →Connecting the store to the systems behind it.

