pawsibly-yours

How We Merged Two National Rescue Feeds Into One Deck and Left the Application With the Rescue

Pawsibly Yours' Dog Adoption Matching App

The Objective

Adoptable dogs are scattered across individual rescue sites and two large national aggregators that duplicate each other heavily. Even once an adopter finds a listing, a raw listing tells them almost nothing about whether that dog suits their home, their working hours or their experience. We built a mobile app over a merged, de-duplicated feed from Petfinder and RescueGroups, with a lifestyle questionnaire driving the match, an AI-written compatibility explanation on every dog, moderation for user-submitted dogs, and the formal adoption application deliberately handed back to the rescue that holds it.

Service Tags

Cross-Platform App Development Web Application Development Backend Development AI Integration

Industry Tags

Pet Adoption Animal Welfare Consumer Marketplace

Tech Stack

React Native (Expo) Sentry RescueGroups v5 React 18 Vite NestJS PostgreSQL 16 Redis 7 BullMQ AWS Firebase Cloud Messaging StoreKit 2 Google Play Billing OpenAI GPT-4o-mini Petfinder v2

The Impact

2
National rescue feeds merged into one deck
Petfinder v2 and RescueGroups v5, both live, pulled on a cron and de-duplicated against each other.
3
Sources feeding the same card deck
Aggregator listings, user submissions and admin submissions, with moderation on the last two.
1
Compatibility writeup generated per dog
Written against the adopter’s own questionnaire answers rather than the listing alone.
Adoption applications processed in the app
The formal application stays with the source rescue, by design.
The Client

A Founder Who Had Seen the Same Dog Four Times in One Afternoon

Samantha Dean came to us with a consumer adoption app and an unusually disciplined view of what it should not do. She was not trying to become the rescue. She was trying to fix the part of adoption that happens before anyone fills in a form: finding a dog that actually fits.

That constraint shaped the build more than any feature in the brief. It meant the product could be judged on match quality rather than on application volume, and it meant the rescues stayed in control of their own process.

The Problem

Two Aggregators, One Dog, and No Idea Whether It Suits You

Petfinder and RescueGroups both index rescues nationally, and a rescue listing on both appears twice to anyone searching across them. An adopter scrolling a combined feed meets the same dog repeatedly under slightly different names, photos and descriptions, with no way to tell it is one animal.

The deeper problem is that a listing describes a dog rather than a fit. Breed, age, weight and a paragraph written by a volunteer say nothing about whether this dog will cope with a ten-hour workday, a small apartment, a toddler, or a first-time owner. Adopters are left inferring suitability from photographs, which is how dogs end up returned.

And any app that inserts itself into the adoption process risks making things worse. Rescues have vetting procedures, home checks and their own application forms for good reasons, and a third-party app that intercepts the application replaces a process built on judgement with one built on conversion.

pawsibly-yours-admin-dashboard
Our Approach

We Fixed the Feed Before We Built the Swipe

The interface people picture when they hear the brief is the card deck. The deck is the easy part. A swipe experience over a feed that shows the same dog three times is worse than no app, so the merge and the de-duplication went in first.

A Cron Puller With De-Duplication Underneath

Both APIs are pulled on a schedule through BullMQ and Redis and reconciled into one index. Matching records across two sources that describe the same animal differently is the hard part of this product, and it runs continuously rather than at import, because rescue listings change and disappear on their own timetable.

The Questionnaire as the Match Input

Onboarding captures lifestyle answers and hard filters before the adopter sees a single dog. Hard filters remove what cannot work at all, and the questionnaire drives the ordering of what remains, so the deck an adopter swipes is already shaped by their home rather than by recency.

An LLM Writeup, Behind an Adapter

Each dog detail carries a compatibility explanation generated against that adopter’s answers. We built it through a provider-agnostic adapter with GPT-4o-mini as the current model, because the AI layer in a consumer app is the component most likely to change on price or capability, and swapping it should be a configuration change rather than a rewrite.

The Application Stays With the Rescue

A right swipe favorites the dog and the detail view links out to the rescue’s own application. We recognised the pattern from other marketplaces that sit in front of a regulated or judgement-based process: intercepting the transaction wins short-term engagement and loses the supply side. The rescues keep their vetting, and the app keeps its role.

Moderation on Everything Users Submit

Users and admins can submit dogs that are not in either aggregator. Every one passes through admin moderation before entering the deck, because an unmoderated submission path on an adoption app is an opening for sellers.

What We Built

14 Modules Across a Mobile App, an Admin Web Panel and a Data Layer

Each module maps to a role and a function. The data layer feeds the deck everything it shows.

Mobile app (iOS + Android)
Admin web
Data layer
How It Was Built

Built Around Two APIs We Do Not Control

Petfinder and RescueGroups are external dependencies with their own rate limits, outages and schema decisions. The ingestion runs as scheduled BullMQ jobs against Redis so a failed pull retries without taking the deck down, and the app reads from the merged index rather than from either API directly. An adopter swiping during a Petfinder outage sees the index as of the last successful pull.

NestJS with TypeORM over PostgreSQL 16 carries the API, deployed on auto-scaling EC2 behind Caddy with CloudWatch and Sentry watching it. The mobile client is Expo-managed React Native, which keeps the iOS and Android builds on one codebase and one release cycle.

The LLM calls run asynchronously rather than on the swipe. Generating a compatibility writeup at the moment a card is opened would put a model latency in front of the most-used interaction in the app, so the writeups are produced and cached against the adopter profile ahead of the detail view.

Outcome

One Deck, De-Duplicated, Ordered by Fit

An adopter answers a lifestyle questionnaire, sets hard filters, and swipes a deck drawn from both national aggregators plus moderated submissions, with duplicates already removed. Opening a dog shows a compatibility explanation written against their own answers, and applying takes them to the rescue that holds the dog.

Administrators moderate submissions, manage users, read a KPI dashboard, and configure both the subscription tiers and the LLM layer without a deployment.

The app is in build. These describe the system as designed rather than results in market, and this section needs rewriting with real figures once it has launched.

Testimonials

“Everyone who pitched me wanted to build the application flow, because that is where the money looks like it is. The rescues would have refused to work with us within a month. Leaving that alone was the decision the whole thing rests on.”

Founder

Pawsibly Yours

Building a consumer product on top of data sources that duplicate each other and change without warning?

We have built the ingestion layer before, and we know it decides whether the rest of the app is worth using.

Start the conversation