The situation
Taptok provides digital business card and contact management infrastructure for Gulf businesses. Each business account is fully isolated \u2014 its own contacts, sharing events, analytics, and profile data. At 100K+ monthly transactions across thousands of tenants, the single-database architecture that worked at launch was becoming the bottleneck. The specific problem was contention between query types. Transactional queries \u2014 creating contact records, logging a card share, updating profile data \u2014 need to be fast and consistent. Analytical queries \u2014 report exports, dashboard aggregates, usage summaries \u2014 are heavy and acceptable to be slightly stale. On a shared database, a long-running analytical query can lock rows or consume I/O that slows down transactional operations for active users. We designed a tenant-based sharding scheme. Tenants are distributed across shards based on a consistent hashing strategy. Application-level routing directs queries to the correct shard transparently \u2014 the application code doesn't know which shard it's talking to. Adding capacity means adding a shard, not vertically scaling a single server. Analytics was completely decoupled. Events flow into Redis, batch jobs aggregate them on a schedule, and results land in a dedicated reporting store that's never on the transactional query path. Active users see sub-second transactional responses regardless of the reporting workload. TDD was enforced throughout the rebuild. Every service class has test coverage before shipping \u2014 the team can change things with confidence.
What had to change
Single-database architecture was approaching capacity. Long analytical queries competed with transactional queries for I/O and locks — active users experienced slowdowns during report generation. Without test coverage, modifying core transaction logic was risky. Scaling vertically was becoming expensive and had a ceiling.
What we changed
Tenant-based sharding with consistent hash routing — horizontally scalable, application-transparent. Analytics decoupled to Redis event pipeline → background aggregation → reporting store. Zero analytical query load on the transactional database. TDD enforced throughout rebuild — comprehensive test coverage on all core transaction paths.
What the client gained
- 01 Horizontal sharding — scale by adding shards not servers
- 02 Analytics fully off the transactional database
- 03 AWS (EC2, RDS, Docker) production infrastructure
- 04 TDD throughout — safe to change, safe to ship