emanuelpetre.dev

Building We3

By Emanuel on Mar 14, 2023
The We3 team in a team session

We3 is my latest venture and what I consider my biggest professional achievement. This startup pushed my abilities to the next level technically and challenged me to become a better leader. I founded this company with my partner, Julian, to solve a direct pain point he was experiencing: the difficulty of making new friends as an adult.

The simplest way to describe We3 is a mobile app that helps you make genuine new friendships. Since launching 6 years ago, we have changed the lives of thousands of people by connecting them to compatible groups nearby. We wrote extensively about our story and mission on the website, and it is worth a read.

The core mission is to radically change how painful, awkward, and inefficient it is to connect with people. We aim to remove the randomness that usually leads to meeting a best friend. Instead, We3 combines social science and modern tech to show you your potential best friends nearby, solving the epidemic of loneliness with efficiency and privacy.

It turned out to be a success for many. We see it in the store reviews (over 10,000 5-star ratings) and the millions of messages sent. I can proudly say that I am happy with what we accomplished, what we built, and the impact we had.

How it works

The Quiz

The app starts by presenting statements for you to swipe on. These aren’t static; the statements dynamically adapt to understand your personality well enough to confidently match you later on.

The Matching

With the psychometric profile built in the previous step, the algorithm takes over. This is the “magic” component. Instead of going to random meetups hoping for a connection, our AI applies social science principles to sort through thousands of users, extracting the most compatible matches for you specifically.

The Chat

When we find a match that fits, we present it to you. You can view your compatibility score, shared traits, interests, and goals. Once a group is formed, you can start chatting and work towards meeting up in real life once trust is established.

Under the hood

The Stack

Backend

We3’s backend runs on Postgres and Ruby on Rails (using the Grape gem). It aims to be the source of truth while remaining simple, RESTful, and scalable. Postgres gave us immense power; specifically, its built-in geospatial capabilities allowed us to filter millions of users based on proximity directly within our queries.

The algorithm responsible for high-quality matching was a significant engineering challenge. It had to be scalable, responsive, and highly accurate.

  • Adaptive Profiling: We implemented a system where a user’s answer determines the next question. This allows us to build a complete psychometric profile with the least amount of user input.
  • Data Structure: Organizing this data to efficiently access dynamic statements based on previous answers required meticulous database design.
  • Scalability: Evaluating compatibility based on hundreds of data points is computationally expensive. A naive approach (comparing every user to every other user) would never scale. We had to optimize this to handle millions of accounts.

Once the infrastructure was in place, we faced the nuance of weighting. The power of evaluating compatibility between two users is great, but insufficient for We3, as we match people in groups of three to reduce awkwardness. Maximizing “three-way compatibility” across thousands of users required creative algorithms and constant trade-off negotiations between technical feasibility and product quality.

Behind the scenes, we integrated services like Pusher, AWS, Google Cloud, Firebase, Twilio, and OneSignal to handle real-time updates, live chat, and background processing. The backend is stateless by design, ensuring predictability and ease of testing.

Frontend

The app is built with a hybrid framework, allowing us to use a single codebase for Android, iOS, and the Progressive Web App (PWA). For a long time, I was the sole developer, and at our peak, we were only four. Efficiency was paramount.

We chose Ionic with Angular.js, and the app still runs on this tech today. This hybrid approach allowed us to be present on all platforms, meeting users where they are. The frontend handles complex native functionalities, including in-app purchases, location tracking, and push notifications, by bridging the gap between web tech and native device APIs.

When We Hit the Wall

There’s a specific moment in We3 that matters more than any other. A user has answered dozens of statements, let the algorithm build their psychometric profile, and they’re waiting, right now, to see who we matched them with. It’s the payoff for everything they invested. It’s the moment the product either delivers or loses them forever.

When queries started hanging at scale, that was the exact moment breaking.

A slow but consistent wait time you can design around. An unpredictable one you cannot. The difference is control. 800ms today, 12 seconds tomorrow. Once we crossed into sporadic territory, we had lost control of the experience at the worst possible point in the user journey.

Finding the Problem

I instrumented the backend with NewRelic and let it show me the slowest transactions. The matching query was the obvious culprit, and it made sense once I looked at what it was actually doing:

  1. Find users within a geographic radius
  2. Filter those users against psychometric compatibility data stored as JSONB
  3. Evaluate compatibility across all three members of a potential group, not just a pair

That last constraint is the expensive one. Matching two people is a comparison. Matching a trio that must work for everyone in the group is a combinatorial problem. At thousands of users per city, a naive approach falls apart fast.

The Fixes, in Order

The first pass was query plan analysis by running EXPLAIN ANALYZE on the slow queries and finding where Postgres was scanning instead of using indexes. Adding JSONB indexes on the psychometric fields was the obvious move. JSONB is flexible by design, but that flexibility has a cost at query time without explicit indexing.

The more impactful change was rethinking the order of filtering. We were running psychometric compatibility checks too early, against too large a candidate pool. The fix was to introduce PostGIS, a Postgres extension that treats coordinates as points on a virtual sphere and calculates real-world distances. By filtering on geography first (cheap), we dramatically narrowed the candidate set before touching the compatibility logic (expensive). The sequence matters enormously here: geography is a blunt but fast filter; psychometrics are precise but slow.

That combination resolved most of the performance issues. But as the user base kept growing, we eventually ran into the ceiling of a single Postgres instance. Even well-indexed reads compete with writes at sufficient volume.

Leader/Follower

The architectural change that gave us sustainable headroom was splitting into a Leader/Follower Postgres structure. The leader handles all writes; the follower is a continuously-synced replica dedicated to reads. The matching queries, the expensive ones, go to the follower. The leader focuses on staying current.

The secondary benefit: a clear horizontal path forward. Need more read capacity? Add another replica. It’s not magic, but it’s a reliable lever that doesn’t require rethinking the application layer.

After all three changes (JSONB indexes, PostGIS geographic pre-filtering, and Leader/Follower), queries returned to under a second across the board. More importantly, they stayed there.

The Team

We were bootstrapped from the beginning, investing our own money and revenue from other projects to kickstart We3. As revenue grew, we expanded the team to support continuous improvement.

I hired and mentored a team of developers, overseeing their onboarding and technical growth. My hiring philosophy was distinct: I did not believe in standard technical tests.

I looked for developers with a growth mindset: curious, dynamic, and self-aware, rather than just checking boxes on a tech stack. I evaluated candidates through deep conversation:

  • Asking about their toolsets and thought processes.
  • Discussing decisions that turned out to be mistakes (and how they fixed them).
  • Asking them to explain code they were proud of.

I found this approach told me much more about a candidate’s problem-solving ability and communication skills than an arbitrary coding test. It was also more respectful of their time.

Once hired, onboarding was streamlined via Docker. I maintained a hands-on mentorship role, reviewing Pull Requests closely not just to check code, but to align on design patterns, logic, and best practices.

Market Fit and Viability

As a product, We3 solves a deep problem for a specific set of “ideal users.” However, we faced challenges in scaling our reach financially. The stigma around loneliness made virality difficult, and we struggled to build a sustainable paid growth channel or attract the right investors for the next phase.

Today, We3 is self-sustainable and continues to grow, but at a slower pace than required for a venture-scale return. It generates revenue, but not enough to sustain the aggressive team expansion we originally aimed for. We now treat it as a successful, sustainable lifestyle business rather than a high-growth startup.

Emanuel Petre | Software Engineer.