Hacker News clone demonstrating how to build with Prisma in a real-world application.
-
Clone the repository:
git clone git@github.com:luanvdw/prisma-hackernews-app.git && cd prisma-hackernews-app
-
Install dependencies:
npm install
-
Set up your environment variables:
cp .env.example .env
Add your DATABASE_URL && DATABASE_URL_DIRECT in the
.env
file. -
Set up the database and run migrations:
npx prisma migrate dev
-
Seed the database:
npx prisma db seed
This repository includes two benchmark scripts designed to evaluate different aspects of Prisma Accelerate's performance:
- Distributed Benchmark: Simulates a distributed environment to evaluate database performance with Accelerate.
- Cache Benchmark: Load tests Accelerate's caching functionality.
This benchmark script simulates an environment to evaluate database performance with Prisma Accelerate in a distributed setting. The script is designed to:
- Simulate multiple concurrent serverless function invocations by spawning separate Node.js processes.
- Measure the performance of database queries under high concurrency.
- Evaluate the effectiveness of connection pooling in a serverless-like context.
- Evaluate the effectiveness of Prisma Accelerate in globally distributed applications.
To run the distributed benchmark:
npm run benchmark:distributed
This benchmark script focuses on load testing Prisma Accelerate's caching functionality. It is designed to:
- Simulate a high number of concurrent requests to test cache performance.
- Measure response times for cached and non-cached queries.
- Evaluate the effectiveness of Accelerate's caching strategy.
- Provide insights into cache hit rates and performance improvements.
To run the cache benchmark:
npm run benchmark:cache
Both benchmarks will output detailed performance metrics, including:
Average response times Median, 95th percentile, and 99th percentile response times Cache hit rates (for the cache benchmark) Total execution time
These metrics will help you understand the performance characteristics of Prisma Accelerate in different scenarios and optimize your database interactions accordingly.
Accelerate's cache invalidation works by allowing you to tag cached queries and then selectively invalidate those tags when needed.
Here's how it functions:
- Tagging: When caching a query, you can add one or more tags to it.
await prisma.post.findMany({
cacheStrategy: { ttl: 300, tags: ["posts"] },
})
- Caching: Accelerate stores the query results in its global cache, associated with these tags.
await prisma.$accelerate.invalidate({
tags: ["posts"],
})
- Invalidation: When data changes, you can invalidate specific tags using the invalidation API.
- Result: All cached queries with the invalidated tags are removed from the cache, ensuring fresh data on the next query.
This system provides a flexible way to maintain cache freshness without having to invalidate the entire cache, balancing performance gains from caching with data accuracy needs.
In the repo you can run the following command to similate a page viewing a bunch of posts:
npm run posts:view
and then run the edit command to invalidate the cached results from that view.
npm run posts:edit
Both of these commands use the posts.ts
file, check it out to see how it works. Play around with different values.
*Note that Accelerate's cache invalidation is currently experimental and may change in the future.
The database schema consists of four main models:
- User: Represents registered users who can create posts, comments, and votes.
- Post: Represents submitted stories or links, created by users.
- Comment: Represents user comments on posts or replies to other comments.
- Vote: Represents upvotes or downvotes cast by users on posts or comments.
erDiagram
User ||--o{ Post : creates
User ||--o{ Comment : writes
User ||--o{ Vote : casts
Post ||--o{ Comment : has
Post ||--o{ Vote : receives
Comment ||--o{ Vote : receives
Comment ||--o{ Comment : replies-to
User {
String id PK
DateTime createdAt
DateTime updatedAt
String username
String email
String password
Int karma
}
Post {
String id PK
DateTime createdAt
DateTime updatedAt
String title
String url
String content
String authorId FK
}
Comment {
String id PK
DateTime createdAt
DateTime updatedAt
String content
String authorId FK
String postId FK
String parentId FK
}
Vote {
String id PK
DateTime createdAt
DateTime updatedAt
Int value
String userId FK
String postId FK
String commentId FK
}