Real estate marketplace · Data engine · Live
42,000 listings, fresh every 15 minutes.
LandBids is a land marketplace and auction site. The product lives or dies on one thing: are the listings real, current, and showing photos? We built the engine that keeps them that way, then moved the whole thing onto infrastructure the client owns without taking the site down.
- Client
- LandBids
- Industry
- Real estate, land and auctions
- Our part
- MLS sync, photo pipeline, infrastructure, security
- Status
- Live at landbids.com
By the numbers
- 42,899: Active listings kept in sync (September 2026)
- 15 min: From an MLS change to the site
- 1.2M: Listing photos resized, compressed and stored
- 1 to 5 min: Time to first photo on a new listing, down from 26 to 41
Source: production database and sync service logs, August to September 2026.
A listing site is only as good as its data.
LandBids pulls its inventory from the MLS. A serverless sync job is fine at a few hundred listings. At tens of thousands it runs into time limits, and when a sync quietly falls behind, nothing on the site tells you. New listings don't appear, prices go stale, and sold land keeps looking available.
Photos were the other problem. MLS photo links expire in about an hour, so every image has to be copied, resized, and stored by the site itself. A listing without a photo is a listing nobody clicks.
The team needed the boring part to just work, so they could spend their time on buyers, sellers, and auctions.
The data engine and the infrastructure under it.
- A 15-minute MLS sync: A dedicated background service that asks the MLS for everything changed since its last run, maps it into LandBids' format, and never overwrites the fields the team manages by hand, like claimed or featured listings.
- A photo pipeline: Every photo is downloaded, rotated, resized to 1920px and recompressed before it's stored. New listings get their first photo processed first, so fresh inventory shows up looking finished.
- A nightly clean-up with a safety valve: Listings the MLS no longer shows as active are taken off the market every night. If the feed ever comes back empty or would wipe out more than half the site, the job stops and alerts instead.
- Link previews that work: A small service that gives every shared listing a real preview card on Facebook, LinkedIn, iMessage and Slack, with the photo and price. Before, shared links showed nothing.
- Infrastructure the client owns: We moved the database, file storage and hosting onto LandBids' own accounts (Supabase, Cloudflare R2, Vercel), with separate staging and production. The cutover took 40 minutes, in an evening window.
- Access rules and release checks: Agent contact details require a signed-in account, every user role has an automated test, and changes go to staging before production.
What happens between an agent listing a property and a buyer seeing it.
- Check for changes: Every 15 minutes the sync service asks the MLS for anything new or changed since its last saved position.
- Translate the record: Each listing is mapped into LandBids' format. Fields the LandBids team controls are left alone.
- Process the photos: Images are downloaded, resized and compressed, newest listings first, and stored on the client's own storage.
- Hide it until it looks right: Search and the homepage wait for a listing's first photo before showing it, so buyers never see a blank card.
- Watch the watcher: The sync's saved position only moves forward. If it stops moving, an alert goes out.
- Clean up nightly: Closed and expired listings are marked off-market. Nothing is deleted, and a bad feed can't empty the site.
The guardrails are the product.
A bad feed can never empty the site
Every night we retire listings that closed in the MLS. If the feed comes back empty or would take more than half the site offline, the job stops and tells a human instead of guessing.
const feedIds = await adapter.activeIds();
if (feedIds.size === 0) {
await ctx.alerts.notify(key, "reconcile aborted: feed returned zero active IDs");
return;
}
const dbIds = await store.activeMlsIds(adapter.mlsSource);
const missing = dbIds.filter((id) => !feedIds.has(id));
// Safety valve: a feed hiccup must not mass-off-market the site.
if (dbIds.length > 500 && missing.length / dbIds.length > 0.5) {
await ctx.alerts.notify(key, `reconcile aborted: ${missing.length}/${dbIds.length} would go off_market`);
return;
}
const marked = await store.markOffMarket(adapter.mlsSource, missing);
Every photo, optimized, with a fallback
1.2 million photos go through this function. If processing ever fails, the original is stored and the failure is logged, so a listing never ends up with a broken image.
export async function optimizeImage(input: Buffer, opts: OptimizeOpts) {
try {
const buffer = await sharp(input, { failOn: "none" })
.rotate() // honor camera orientation
.resize({ width: opts.maxWidth, withoutEnlargement: true })
.jpeg({ quality: opts.quality, mozjpeg: true })
.toBuffer();
return { buffer, contentType: "image/jpeg", ext: "jpg" };
} catch (err) {
failureCount++;
if (failureCount <= 5 || failureCount % 100 === 0) {
log.error({ err: (err as Error).message, failureCount },
"sharp optimize failed; storing original bytes");
}
return { buffer: input, contentType: "image/jpeg", ext: "jpg" };
}
}
Built with: React, TypeScript, Supabase (Postgres, auth, edge functions), Node on Railway, Cloudflare R2, Vercel, sharp, MLS Grid API
Fresh inventory, real photos, and a site the client controls.
The listings on landbids.com are now the listings in the MLS, give or take fifteen minutes.
- 42,899 active listings in sync, updated every 15 minutes.
- Before switching over, the new engine was checked listing by listing against production: 41,006 listings, zero real differences.
- About 15,800 closed or expired listings retired on the first nightly clean-up, so buyers stop clicking on land that's already sold.
- Time to first photo on a new listing cut from 26 to 41 minutes at peak to 1 to 5 minutes.
- Database, storage and hosting moved to the client's own accounts in a 40-minute cutover: 72,219 listings restored, 47 of 47 checks passed.
Your product runs on data you don't control.
- You pull listings, inventory, or pricing from a feed or partner API.
- Things fall out of sync and nobody notices until a customer does.
- Your app was built fast and now needs to run like a real business.
Book a call with Josh | See the Fix-it Sprint
Frequently asked questions
- What did Solid Giant build for LandBids?
- The data engine and production infrastructure behind landbids.com: a 15-minute MLS sync for 42,000+ listings, a photo pipeline for about 1.2 million images, a nightly clean-up with safety limits, link previews for shared listings, and a move to infrastructure LandBids owns.
- How often do LandBids listings update?
- Every 15 minutes. A background service asks the MLS for anything changed since its last run and applies it, with photos processed newest-first.
- Can you fix an app that falls out of sync with its data source?
- Yes. Most sync problems come from jobs that can time out, fail silently, or overwrite each other. We move the work into a dedicated service with saved positions, alerts, and safety limits, then prove it against production data before switching over.
All work