Bondly Pet Care Platform
Pet-care marketplace with subscriptions, service credits, Stripe payments and OneSignal notifications. Sameem led the backend as an engineer at Webrange Solutions in 2024. Live at bondlypets.com.

Facts about the build and who it was for. Any figure here is shown on a public store listing or site linked on this page — how we present portfolio work.
Project Story
Pet care services struggled with managing subscriptions, credits, payments, and notifications efficiently.
As an engineer at Webrange Solutions, Sameem led the backend: Node.js and MongoDB with Firebase, Stripe subscription billing with credit-based service unlocking, OneSignal notifications, deployed on AWS.
The platform is live at bondlypets.com.
Project Details
Bondly connects pet owners with care professionals. Sameem worked on it as an engineer at Webrange Solutions and led the backend in 2024: Node.js and MongoDB with Firebase, Stripe subscription billing, credit-based unlocking of services, OneSignal push notifications for the Flutter app, and deployment on AWS.
Tech Stack
Where to See It
Category
Node.js & FirebaseBondly is a pet-care marketplace in the Netherlands that connects pet owners with local carers for dog walking, day sitting and overnight care. Sameem worked on it as an engineer at Webrange Solutions, where he led the backend in 2024. He designed and deployed a Node.js and MongoDB backend that served Bondly's Flutter mobile app, automated Stripe subscription billing and credit-based service unlocking, and built push notifications on OneSignal, with Firebase also in the stack. The live site is bondlypets.com.
What you can check
- Live site: bondlypets.com, a pet-care marketplace for dog walking, day sitting and overnight care
Each item points to something public: a store listing, a live site or a demo build. See our terms for how we present portfolio results.
What is Bondly, and what did Sameem work on?
Bondly is a marketplace for pet care. Its public site, bondlypets.com, lists local, certified carers offering dog walking, day sitting and overnight care, booked through an app, and names Rotterdam and Amsterdam as the cities where the service is live. Sameem worked on Bondly as an engineer at Webrange Solutions, and in 2024 he led the backend: the server side that the Flutter mobile app talks to.
He designed and deployed the backend on Node.js and MongoDB, automated subscription billing cycles and credit-based service unlocking, and built a push notification system on OneSignal. Stripe handled the payments, and Firebase and AWS complete the stack. The sections below explain why a backend of that shape is built the way it is.
Why do subscriptions and credits have to be treated as one system?
Subscriptions, credits, payments and notifications look like four features, but on a platform like this they behave as one system, because each depends on the state of the others. A subscription is a schedule: it renews, it charges, and it succeeds or fails. A credit is different in kind. It is an entitlement the customer has already paid for and not yet used, so it sits between the money and the service and has to stay correct while both move independently. A renewal changes a balance. A balance change is something the customer may need to be told about. A failed payment has to reach back into whatever the customer is currently entitled to.
The engineering consequence is that correctness is a property of the whole rather than of any one part. A billing change that never reaches the credit balance, or a balance that moves without the customer being told, is a defect even when every component behaved exactly as written. That is why the work Sameem did, automating the billing cycle and tying access to services to credits, is backend work rather than a payment-screen feature: the rules that connect money to entitlement have to live in one place that the customer's device cannot reach.
Why is credit management harder than ordinary subscription billing?
A subscription on its own is a schedule. Credits add a balance that changes outside that schedule, every time a customer uses one, and a balance that two systems can both believe they own is the classic source of quiet accounting errors. The safe general pattern is to treat the balance as a derived value rather than a stored number: record every event that grants or consumes a credit as an immutable entry, and compute the balance from the entries. Appending is cheap, and a history that cannot be edited can be replayed, audited and explained to a customer who disputes it. A single mutable counter can only be overwritten, and once it is wrong there is nothing left to reconstruct it from.
The second difficulty is concurrency. Two requests that each check a balance of one and then spend it will both succeed unless the check and the spend happen as one atomic operation, and mobile clients retrying over an unreliable network make that race common rather than theoretical. The usual defences are a conditional write that fails when the balance has moved, or a uniqueness constraint on the consuming action so a retried request cannot be counted twice. Both amount to the same rule: the decision to spend and the act of spending cannot be separate steps. Billing then has to agree with the ledger over time. A renewal that grants credits, a payment that fails after they were granted, a refund, a cancellation mid-period: each one asks what should happen to credits already issued. Those are product decisions.
Why was Node.js a reasonable choice for this backend?
The backend runtime is Node.js, working with MongoDB, Firebase, Stripe and OneSignal. Read as a list of dependencies, that points to a service whose work is mostly waiting: a query against the database, a call to Stripe, a notification handed to OneSignal, a webhook arriving from a vendor. Very little of it is computation. Node.js is built for exactly that profile, because its event loop handles many concurrent connections in a single process without a thread parked on each one, and a request that spends most of its life waiting for a network response costs a callback rather than a stack. When a backend is mostly an orchestrator between a database, a mobile app and outside vendors, there is no CPU-bound stage to be penalised by a single-threaded execution model.
The second reason is practical. Every vendor in this stack speaks JSON over HTTP and ships a maintained JavaScript SDK, and MongoDB stores documents that map directly onto JavaScript objects, so one language covers the server, the vendor integrations and the shapes that describe a subscription or a credit grant. A backend of this kind is also a webhook receiver, which is a specific obligation. Deliveries retry, duplicate and arrive out of order by design, so each handler has to be safe to run more than once, accept the event quickly and do the slower work afterwards.
How do MongoDB and Firebase divide the data work?
Sameem designed the backend on Node.js and MongoDB, and Firebase is also part of the stack. In a mobile product the two usually do different jobs. A server-side database such as MongoDB holds the records the backend owns: accounts, bookings, subscriptions, credit entries. Firebase is less a database than a set of client-facing services with mobile SDKs attached, such as authentication, a synchronising datastore, file storage and the messaging layer beneath push notifications. The general reason to pair them is that Firebase's SDKs give a Flutter app live updates and tolerance of poor connectivity, while the server keeps the authoritative copy of anything that involves money.
That split is a division of trust rather than duplication. A device can be allowed to read its own balance, but it cannot be allowed to write one, because the app runs on hardware the customer controls, and anything it is permitted to change it can change arbitrarily. Money and entitlements therefore belong behind a server, with the client given read access at most. The trade-off worth naming is the query model. Document stores, MongoDB included, are quick at fetching a known record and less natural for the aggregate questions a ledger invites, such as totals across a period, so data tends to be shaped for the screens that read it and some facts end up written in more than one place. That cost is paid in write complexity rather than read speed.
How do Stripe and OneSignal cover payments and notifications?
Stripe handled payments, and Sameem automated the subscription billing cycles on it. A subscription business hands a payment integration a particular set of problems. A single charge succeeds or fails once and is finished. A recurring arrangement runs indefinitely, and with it come renewal dates, proration when a plan changes, cards that expire mid-term, failed payments that retry on a schedule, cancellations that take effect at different moments depending on terms, plus tax, refunds and receipts. Each is a small state machine, and owning them means owning all of them correctly for as long as the business has customers. Delegating them puts card networks, issuers, currencies and retry behaviour with a system built for nothing else. What stays local is the mapping between a paid plan and the credits it grants, which no processor can know.
OneSignal covers notifications, and specifically the part of push delivery that is tedious rather than interesting. A notification has to reach Apple's and Google's services in the form each expects, addressed to a device token that the operating system can rotate without warning and that becomes invalid when the app is uninstalled. Tokens therefore have to be collected, refreshed, deduplicated across a customer's devices and retired when the platforms report them dead, and none of that work distinguishes one product from another. A delivery service also absorbs fan-out, so sending to a group is one request rather than a loop the backend has to schedule and retry. The question left on the backend side is which events deserve a notification at all, since a system that tells a customer about every balance change is one they will mute.
Why does the platform need a server on AWS when Firebase is managed?
AWS is the deployment target for the backend. The boundary is worth reading literally: Firebase supplies client-facing services, and the server on AWS carries the part of the system that has to be a server. Some work simply cannot live on a device. Webhook endpoints have to sit at a stable address that a vendor can reach with no user present. Secrets that sign requests to a payment processor cannot ship inside a mobile app. Renewal handling, credit grants and reconciliation are background work that runs whether or not anyone has the app open. A general-purpose server also leaves the runtime ordinary rather than tied to one vendor's execution model.
Where can you see Bondly?
Bondly's public site is bondlypets.com. It presents the service as live in Rotterdam and Amsterdam, lists dog walking, day sitting and overnight care, and links to Bondly's apps on the App Store and Google Play. The site notes that prices vary per carer and service, and that bookings are made in the app.
Sameem's part was the backend, which a visitor never sees directly. The sections above cover that backend as it stood when he led it at Webrange Solutions in 2024.
Why this stack
- Node.js is the backend runtime. The work is orchestration between network services rather than computation: queries against the database, calls to Stripe, notifications handed to a delivery service and webhooks arriving back. An event loop suits that profile, since many mostly idle, waiting connections cost callbacks instead of parked threads, and there is no CPU-bound stage to be penalised by single-threaded execution. Every vendor named here speaks JSON and ships a JavaScript SDK, so one language covers the server, the integrations and the shapes describing a subscription or a credit grant.
- MongoDB is the backend's database. A document store maps directly onto the JSON a Node.js service already handles, and records such as a booking or a subscription can carry the fields they need without a migration for every new attribute. The cost is that aggregate questions, such as totals across a billing period, are less natural than in a relational database, so data is shaped for the reads the product makes.
- Firebase is part of the stack beside MongoDB. It is a set of client-facing services with mobile SDKs: authentication, a synchronising datastore, storage and the plumbing beneath push. Clients subscribe to data rather than polling, and the SDKs cache locally and reconcile when connectivity returns, which suits a mobile app used away from reliable networks. Writes that move money stay behind the server either way.
- Stripe is the payments vendor, and Sameem automated subscription billing cycles on it. Recurring revenue carries its own obligations: renewal schedules, proration on plan changes, expiring cards, failed-payment retries, cancellation timing, refunds, tax and receipts. Each is its own state machine, and owning one means owning all of them indefinitely. Delegating them puts card networks, issuers and retry behaviour with a system built for nothing else. The application still owns what a processor cannot know, namely which credits a plan grants.
- OneSignal is the notification service. Push delivery means reaching Apple's and Google's services in the form each expects, addressed to device tokens that rotate without warning and expire when an app is removed. Collecting, refreshing, deduplicating and retiring those tokens is continuous work that differentiates no product. A delivery service also absorbs fan-out, so addressing a group is one request rather than a retry loop the backend schedules itself. What remains on the application side is deciding which events are worth interrupting someone for.
- AWS is the deployment target. The division it implies is straightforward: Firebase faces the client, and the server on AWS runs the parts that have to exist without one. Webhook endpoints need a stable address a vendor can reach when no user is present. Signing secrets cannot ship inside a mobile app. Renewals, credit grants and reconciliation are background work that runs regardless of who has the app open.