Client work · 2016–now · for KARM Thrift Stores

ThriftTrac

Business software for thrift stores, ten years on.

Donations and donors, pickups and events, and every store's numbers, for thrift store organizations that each see only their own. I started on it in 2016, and today it's the platform OnTrac and the Pricing Guide are built on.

Client
KARM Thrift StoresFour projects, 2016–2024
I built
Rails Web App & Engine
With
Ruby, Rails, Active Admin, MySQL, Sidekiq
ThriftTrac's admin on demo data, on its green: the Donations list, and in front of it a new donation, with a tile for each category and its count.

The brief

The back office for a thrift store

ThriftTrac is business software for thrift stores: the donations and the donors and partners behind them, the pickups and events, the numbers from every store's processing and retail, and the records from its point of sale. It came to Lotus in 2016 to be made fast and safe, and I've worked on it every year since.

The challenge

An aging app, asked to do more

It arrived as a slow, error-prone Rails 3.2 app with no test coverage, full of leftovers from earlier attempts at changing it. Then it had to become more than one app, as a point of sale and later a pricing guide both needed the same data and the same rules as the back office.

What I made

One engine, three apps, kept current

I audited it and fixed what mattered first, then moved its models, jobs and services into an engine, a private gem that the web app, OnTrac's API and the Pricing Guide all run on. It has gone from Rails 3.2 to Rails 8.1 along the way, and I still look after it.

ThriftTrac in production, September 2026

  • 25 milliontransactions at the point of sale since 2018
  • $625 milliontaken at the register
  • 5.8 milliondonations recorded
  • 333active locations, in 73 organizations
The Donations list in ThriftTrac’s admin, on demo data: the newest donations first, each with its date, partner, status, item count, suggested value and total value, beside filters by donor, partner, date, status and store.

2016

The Audit

ThriftTrac had been built by another team since 2013, and by the time it came to me in the fall of 2016 it was a horribly slow and error-prone application. It had no test coverage, and it was full of artifacts from earlier attempts at changing its infrastructure, down to database tables for a boat maker, another client of the developers before me, that nothing in the code used.

So I started with an audit. I reviewed all of the code for security vulnerabilities and best practices, found several bugs nobody knew about and the code that could go, and delivered it to the client as a list to work through. Then I prioritized it, and spent the first few months fixing it.

The slowness came first. With New Relic watching the live site, I found the missing database indexes, the counts that were worked out again on every page and the queries that didn’t need to run, and made the site about four times faster with very little code. I also brought Rails up to its latest security release, took out the empty test suite and the unused scheduling and newsletter code, and started a real test suite in RSpec the following spring.

An organization in ThriftTrac’s internal admin, on demo data: its name, subdomain and website, then Module Access, with donations and events, metrics, the point of sale, the Pricing Guide and the shared pricing library each switched on, and its point of sale settings.

Many organizations

One Back Office, Many Stores

ThriftTrac isn’t one thrift store’s back office. It’s sold to thrift store organizations as a product, and each one signs in at its own address and sees only its own donors, stores, drawers and numbers. Every record belongs to an organization, and every screen and every permission is scoped to it.

Each organization also gets the parts it pays for, switched on one by one: donations and events, business metrics, the point of sale, the Pricing Guide and its shared library.

For the people using it, it’s where a donation is scheduled, picked up and receipted, where the donor and partner libraries are kept and cleaned up, and where a store’s processing, retail and wholesale numbers come together on a dashboard.

Between them, its donor libraries hold more than 900,000 donors.

Taking in a donation, on demo data: the donor found by phone number, their partner, Maple Street Church, and a tile for each category, Clothing, Shoes, Linens, Electronics, Media, Appliances, Furniture and Seasonal, each with its count between minus and plus buttons.

2018

Pulling Out the Engine

In 2018 KARM wanted a point of sale, which became OnTrac, an iPad app, and it needed an API. That API needed to be separate from the web app, so it could be scaled on its own, while sharing the same logic.

So in February 2018, the same week the web app moved to Rails 5, I extracted ThriftTrac’s core into a Rails engine: its models, and later its jobs and services, in a gem of their own on a private gem host. The web app installed it that month, and a month later the API was started on it.

Time has proven a separate API a very wise decision. The main web app is the more memory-intensive of the two, and keeping the API lean has meant I can scale it more cheaply and respond to demand as it comes. Since May 2018, ThriftTrac has recorded about 25 million transactions from its point of sale, with $625 million taken at the register. When the Pricing Guide came along in 2024, it was built on the same engine, with no models of its own at all.

Step through the years here to see how the platform grew.

ThriftTrac2016

  • The web appDonations, donors, stores and their numbers, in Active Admin

No engine: every model lives in the one app

MySQL

Rails
3.2
Ruby
2.2
Tests
None
Runs on
Elastic Beanstalk
2016 One app, three years old, with no test coverage

ThriftTrac2018

  • The web appThe back office
  • The POS APIFor OnTrac, the iPad point of sale

The engine: the thrift_trac gem, with the models, jobs and services

MySQL

Rails
5.1
Ruby
2.3
Tests
RSpec
Runs on
Elastic Beanstalk
2018 The models move into an engine, so a second app can share them

ThriftTrac2024

  • The web appThe back office
  • The POS APIFor OnTrac
  • The Pricing GuidePricing on the store’s iPads and Chromebooks

The engine, now with pricing in it

MySQL

Rails
6.0 → 7.2
Ruby
2.6 → 3.3
Updates
Dependabot
Runs on
Heroku
2024 A third app on the engine, and four Rails upgrades in one year

ThriftTrac2026

  • The web appThe back office
  • The POS APIFor OnTrac
  • The Pricing GuideFor pricing

The engine, shared by all three apps

MySQL

Rails
8.1
Ruby
4.0
Tests
In a real browser too
Runs on
Heroku
Today Three apps on one engine, on Rails 8.1 and Ruby 4.0

Keeping it current

From Rails 3.2 to Rails 8.1

ThriftTrac was started on Rails 3.2 in 2013, and I’ve brought it forward a version at a time ever since. It went to Rails 4.2 in 2017, to Rails 5 in 2018 on the way to the engine, and on through Rails 6 and 7 to Rails 8.1, with Ruby going from 2.2 to 4.0 along the way.

Today it runs on the latest Rails and Ruby, on Heroku, with Dependabot keeping everything else up to date and tests that drive a real browser through its screens on every pull request, before anything is deployed.

An organization’s Brands in ThriftTrac’s admin, under its Pricing Guide menu, on demo data: six brands, each with a tier of A, B or C, filtered by All, Shared Only or Local Only, with IKEA from the shared library and the rest the organization’s own, above the ThriftTrac logo, a green T-shirt beside its name, in the footer.

Running the platform

An Admin of Its Own

The most recent big pieces of work on ThriftTrac have been the tools for running it. In 2024 I gave the platform an internal admin, separate from the one organizations use, where a super admin sets up a new organization, switches its modules on, and configures each of its locations, down to the credentials for its card processor, and keeps count of the locations still missing them.

The Pricing Guide brought a lot of work into ThriftTrac too. Each organization keeps its own categories, brands and price points in its admin, and since 2025 the internal admin has looked after the Shared Pricing Library that organizations can opt into, with a history of every change to a price point. The review queue that keeps that library tidy lives there as well, and its story is on the Pricing Guide’s case study.

The email templates organizations send their donors have default versions in the internal admin too, where they can be edited and previewed.

The Craft

A gem of its own

The engine is a private gem, versioned and published from its own releases, so each app moves to a new version when it’s ready, not when another app changes. It holds about 70 models today, from donations and drawers to price points, with the jobs and services that work on them.

Every record has an owner

The organization comes from the address someone signs in at, and every permission is written against it, so one organization’s records can’t turn up on another’s screens. A new organization is set up from an internal admin, and a system test walks through doing it.

Tested at both ends

The engine has its own suite of more than a hundred spec files, and the web app’s tests include system tests that drive a browser through its screens. The web app’s run on every pull request, against MySQL and Redis, as in production.

Work done in the background

Sidekiq runs the work that shouldn’t hold up a person: emailing each store’s daily summaries, writing the journal entries for QuickBooks Online and, overnight, closing stale shifts and sweeping the Pricing Guide’s brands for duplicates.

More for KARM Thrift Stores

Four projects for KARM Thrift Stores

All the client work

2016 to 2024

  1. 2016
    Still maintainedThriftTracBusiness software for thrift stores, and the platform the rest are built on. You’re reading this
  2. 2018 Still maintainedOnTracA point of sale made for the needs of the thrift industry, on iPad. Read the case study
  3. 2020 No longer runningThrift Shopping NetworkLive, recorded and flash sales of donated treasures online, for the 2020 lockdown. Read the case study
  4. 2024 Still maintainedPricing GuideA shared price guide for thrift stores, on the iPads and Chromebooks in the store. Read the case study