What Is Groundswell-daily-opinion-platform?

Every day, one opinion question goes live on Groundswell. Every player worldwide answers the same question. But the score has nothing to do with your opinion.

After voting, you predict what percentage of Germany voted YES. What percentage of players aged 18–24 voted YES. When results come in — Japan at 41%, Brazil at 81%, a 40-point gap on the same question — your Empathy Score reflects how accurately you predicted those differences, not whether you voted with the crowd.

The leaderboard does not rank who agreed with the majority. It ranks who best understood how people different from themselves think.


What Inspired This

Social platforms have spent 20 years optimizing for agreement. The downstream effect is that people have genuinely lost the ability to predict how groups outside their immediate context see the world. There is no product that makes cross-cultural perspective-taking into a scored, daily game. Groundswell is an attempt to build that.


How We Built It

The architecture uses two AWS databases provisioned through the Vercel Marketplace, each chosen for a specific and technically distinct reason.

Amazon DynamoDB — Vote Ingestion

When a question trends and thousands of players vote simultaneously, DynamoDB's UpdateItem ADD operation increments demographic segment counters atomically — no locking, no queue, no serialization. Ten thousand players from Germany voting in the same 10-second window all increment yes_count on COUNTER#questionId / SEG#country_DE correctly, concurrently.

We used single-table design on the Vercel-managed table. Two item types, distinguished by partition key prefix:

  • VOTE#questionId / PLAYER#playerId — individual vote record with ConditionExpression: attribute_not_exists(pk) AND attribute_not_exists(sk) preventing duplicate votes at the database level, not the application level.
  • COUNTER#questionId / SEG#country_DE — atomic counter incremented with ADD yes_count 1 for concurrent-safe vote tallying.

Amazon Aurora DSQL — Rankings and Aggregates

Three operations required SQL that DynamoDB cannot provide:

Leaderboard ranking uses a SQL window function:

Prediction scoring uses a JOIN between user_predictions and question_aggregates to compute each player's error points in a single query. DynamoDB would need multiple round trips and application-layer joining.

Globally consistent reads: Two players in different countries watching the same live result grid must see identical country percentages at the identical second. Aurora DSQL's active-active architecture eliminates read replica lag — standard PostgreSQL replicas can lag 2–4 seconds, which is observable on a grid updating every 10 seconds.

The Midnight Pipeline

At midnight UTC, a Vercel Cron job reads all segment counters from DynamoDB, computes final percentages, writes them to Aurora DSQL question_aggregates, then uses a SQL JOIN to score every player's predictions and update empathy scores. DynamoDB handles the write throughput during the day; Aurora DSQL handles the relational computation at night.

Amazon Bedrock — AI Question Generation

Daily questions are generated by Amazon Bedrock's Nova Lite model. The prompt specifically requests questions predicted to produce cultural divergence — not consensus. Bedrock returns five candidates with predicted divergence scores. An admin reviews and approves one before it goes live. The predicted divergence score is recorded alongside the actual divergence measured after voting, creating a feedback loop for question quality over time.


Challenges We Faced

Aurora DSQL authentication does not use static passwords. Authentication requires a DsqlSigner token generated from IAM credentials, used as the PostgreSQL connection password. Running locally requires vercel dev, not npm run dev, because the OIDC token is only injected by the Vercel CLI. This took significant debugging time to discover.

DynamoDB IAM scope: The Vercel-provisioned DynamoDB IAM role is scoped only to the auto-created table. We could not create custom tables programmatically. The solution — single-table design on the existing table — turned out to be architecturally superior to what we originally planned. The constraint pushed us toward the pattern AWS actually recommends.

Aurora DSQL limitations vs standard PostgreSQL: Foreign keys are not supported. Index creation requires the ASYNC keyword. Descending index sort orders are not supported. Each of these required schema adjustments discovered during development.


What We Learned

The most important lesson was that database selection should follow access patterns, not habit. DynamoDB and Aurora DSQL are not interchangeable tools — each one is genuinely the wrong choice for the other's workload. Concurrent atomic writes and globally consistent relational reads are opposite requirements. The architecture that emerged from following those requirements strictly is more defensible than anything designed top-down.

Provisioning both databases through the Vercel Marketplace removed infrastructure management entirely. Both were live with auto-injected environment variables in minutes. The interesting engineering work was the database design, not the setup.

Built With

Share this project:

Updates