Files
triqura-ecd/docs/architecture/tech-stack-onderzoek.md
2026-07-09 23:16:28 +02:00

495 lines
21 KiB
Markdown

# Tech Stack Onderzoek — Versies, Alternatieven & Samenhang
> **Type**: Onderzoeksrapport
> **Datum**: 2026-02-14
> **Doel**: Valideer alle technologiekeuzes uit de architectuur op versies, community health, alternatieven en onderlinge compatibiliteit
> **Conclusie**: 5 wijzigingen aanbevolen, 3 aandachtspunten, rest is solide
---
## Samenvatting: Wijzigingen ten opzichte van de architectuur
### Wijzigingen (doorvoeren)
| # | Was | Wordt | Waarom |
|---|-----|-------|--------|
| W1 | Next.js 14 + React 18 | **Next.js 16.1 LTS + React 19** | Next.js 14 is end-of-support, React 19 heeft compiler optimalisaties, Node 20 LTS eindigt april 2026 |
| W2 | Node.js 20 | **Node.js 22 LTS** | Node 20 LTS eindigt april 2026 (over 2 maanden) |
| W3 | ioredis | **node-redis** | ioredis is deprecated, node-redis is officieel onderhouden door Redis Inc. |
| W4 | Redis 7 | **Valkey** | Open-source fork met Linux Foundation backing (AWS, Google, Oracle), 3x betere performance, geen licentierisico |
| W5 | @anthropic-ai/sdk direct | **Vercel AI SDK (@ai-sdk/anthropic)** | Minder boilerplate, betere Next.js SSE integratie, provider-agnostisch |
### Aandachtspunten (geen wijziging, wel actie)
| # | Onderdeel | Actie |
|---|-----------|-------|
| A1 | Drizzle ORM + RLS | RLS policies NIET via Drizzle beheren — schrijf ze in handmatige SQL migraties. Drizzle verwijdert stiekem bestaande policies |
| A2 | Auth.js v5 + Keycloak | Token refresh race conditions bij concurrent sessions. Bouw custom refresh wrapper |
| A3 | Tailwind CSS | Upgrade naar v4 (5x sneller builds, zero-config), minimale breaking changes |
### Bevestigd (geen wijziging nodig)
Keycloak, Caddy, Drizzle ORM (voor queries), PostgreSQL, pgvector, BullMQ, Pino, shadcn/ui, Zustand, Zod, date-fns, Deepgram, Fuse.js, Lucide React, React Hook Form, Hetzner, Docker Compose
---
## 1. Core Framework Stack
### Next.js — upgrade naar 16.1 LTS
| Eigenschap | Huidig (14) | Aanbevolen (16.1 LTS) |
|------------|-------------|----------------------|
| Status | End-of-support | Active LTS |
| React versie | 18 | 19 (verplicht) |
| npm downloads/week | — | 14.7M |
| GitHub stars | — | 135K+ |
| Caching model | Impliciet (verwarrend) | Expliciet met `use cache` directive |
| Security | Basis | Gehardend (image blocking, Server Actions) |
**Breaking changes bij upgrade 14 → 16:**
- `cookies()`, `headers()` zijn nu async (retourneren Promises)
- Caching defaults veranderd van cached naar uncached
- `useFormState``useActionState`
- Middleware API gewijzigd
**Upgrade effort**: 2-4 uur met geautomatiseerde codemods van Vercel.
**Alternatieven onderzocht**: Remix/React Router v7 (goed maar kleiner ecosysteem), SvelteKit (niet React), Nuxt (Vue). Next.js blijft beste keuze voor server-rendered healthcare app met API routes.
### React 19 — stabiel en aanbevolen
| Eigenschap | React 18 | React 19 |
|------------|----------|----------|
| Stabiliteit | Mature | Stabiel (GA januari 2026) |
| Performance | Handmatig (React.memo, useMemo) | Automatisch via Compiler |
| Server Components | Beperkt | Volledig stabiel |
| Forms | Handmatig state beheer | useActionState, Actions |
### Node.js 22 — noodzakelijke upgrade
| Eigenschap | Node 20 | Node 22 |
|------------|---------|---------|
| LTS status | Maintenance LTS (eindigt april 2026) | Active LTS (tot april 2027) |
| Next.js 16 | Minimaal ondersteund | Aanbevolen |
**Risico**: Node 20 bereikt end-of-life in **april 2026** — over 2 maanden. Upgrade is urgent.
### TypeScript 5.9 — geen actie nodig
Huidige 5.x is volledig compatibel met Next.js 16 + React 19. TypeScript 6.0 beta is aangekondigd (februari 2026), 7.0 wordt herschreven in Go. Geen haast.
---
## 2. Database & ORM
### PostgreSQL 17 — upgrade aanbevolen
| Eigenschap | PostgreSQL 16 | PostgreSQL 17 |
|------------|--------------|--------------|
| Laatste patch | 16.12 (feb 2026) | 17.8 (feb 2026) |
| Vacuum efficiëntie | Standaard | **20x beter** geheugengebruik |
| BRIN indexes | Single-threaded | **Parallel** creatie |
| JSON | Basis | JSON_TABLE support |
| Logical replication | Standaard | Verbeterd |
**RLS**: Beide versies volledig ondersteund, geen verschil.
**Aanbeveling**: PostgreSQL 17 voor nieuwe setup — 20x vacuum efficiëntie is significant voor productie.
### Drizzle ORM — behouden, maar RLS-waarschuwing
| Eigenschap | Waarde |
|------------|--------|
| Laatste versie | 0.45.1 |
| npm downloads/week | ~4.7M |
| GitHub stars | 32.8K |
| Bundle size | ~7.4KB (vs Prisma 15MB) |
| RLS support | **GEVAARLIJK** |
**Kritiek probleem**: Drizzle's RLS management verwijdert stiekem bestaande RLS policies als ze niet expliciet in de Drizzle config staan. `drizzle-kit push` past policies niet correct toe.
**Oplossing**: Gebruik Drizzle alleen voor queries en schema. Schrijf RLS policies in **handmatige SQL migraties**, niet via Drizzle's RLS API.
**Vergelijking**:
| Criterium | Drizzle | Prisma | Kysely |
|-----------|---------|--------|--------|
| Bundle size | 7.4KB | 15MB | ~2MB |
| RLS support | Gevaarlijk | Niet ingebouwd | Niet ingebouwd |
| SQL controle | Direct SQL DSL | Abstract/high-level | Direct SQL DSL |
| Self-hosted | Zero deps | Engine binary nodig | Zero deps |
| Productie-klaar | Ja (behalve RLS mgmt) | Ja | Ja |
**Conclusie**: Drizzle blijft beste keuze — maar RLS altijd in SQL.
### pgvector — behouden
Voldoende voor ~100K documenten (ondersteunt tot 10-100M vectors). Geen extra infra nodig.
**Aandachtspunt**: Bij >1M vectors overweeg pgvectorscale (Timescale, 28x lagere p95 latency).
### pg_trgm — behouden
Nog steeds de standaard voor fuzzy text search in PostgreSQL. Geen betere alternatieven.
---
## 3. Auth & Security
### Keycloak 26.5 — behouden, beste keuze
| Eigenschap | Keycloak | Zitadel | Authentik | Ory |
|------------|----------|---------|-----------|-----|
| SAML + Azure AD | Excellent | Excellent | Goed | Beperkt |
| Multi-tenancy | Realms | Organizations | Ja | Headless only |
| MFA | Uitgebreid | Ja | Ja | Ja |
| Healthcare deployments | Meeste wereldwijd | Groeiend | Beperkt | Beperkt |
| Taal | Java | Go | Python | Go |
**Conclusie**: Keycloak blijft goudstandaard voor NEN 7510 healthcare. Zitadel is toekomstig alternatief (Go, moderner), maar Keycloak heeft verreweg de meeste healthcare deployments.
### Auth.js v5 + Keycloak — behouden, met aandacht
Auth.js v5 is stabiel (GA), maar de **Keycloak provider heeft bekende problemen**:
1. **Refresh token race conditions** bij concurrent `useSession()` calls
2. **Session timeout redirects** naar `/api/auth/error` na idle time
3. **Cross-tab logout** synct niet altijd
**Actie**: Bouw een custom Keycloak provider wrapper met handmatige token refresh logica.
### AES-256-GCM (node:crypto) — behouden
Nog steeds de industriestandaard. Onderdeel van TLS 1.3, FIPS 140-3, onderschreven door NSA/NIST/OWASP. Geen betere alternatieven.
### Caddy 2.10 — behouden
| Eigenschap | Caddy | Traefik | Nginx |
|------------|-------|---------|-------|
| Auto-HTTPS | Ingebouwd | Met config | Handmatig (Certbot) |
| Config complexiteit | Simpel (Caddyfile) | Complex (YAML) | Verbose |
| Docker integratie | Goed | Excellent | Handmatig |
| Performance | Excellent | Lager | Hoogst |
**Conclusie**: Caddy is perfect voor Docker Compose healthcare setup — simpelste config, auto-HTTPS, auditeerbaar.
---
## 4. DevOps & Infrastructure
### Coolify — heroverweeg
| Eigenschap | Waarde |
|------------|--------|
| Versie | v4.0.0-beta.462 |
| GitHub stars | 50.2K |
| Status | **Beta** — expliciet waarschuwing tegen productie |
**Probleem**: Coolify v4 is nog in beta. Voor een healthcare systeem is dat een risico.
**Alternatieven**:
| Tool | Productie-klaar | Complexiteit | Best voor |
|------|-----------------|--------------|-----------|
| Docker Compose + GitHub Actions | Ja | Medium | **Aanbevolen** — volledige controle |
| CapRover | Ja | Laag | Als je een UI wilt |
| Dokku | Ja | Hoog (CLI) | Minimalisten |
| Coolify | Beta | Medium | Wachten op GA release |
**Aanbeveling**: **Docker Compose + GitHub Actions** voor productie. Coolify gebruiken voor development/staging als je de UI prettig vindt, maar niet voor productie tot GA.
### Hetzner — behouden
Nog steeds beste prijs/prestatie in EU. Alternatieven onderzocht:
- **Netcup**: Goedkoper maar minder performant
- **Scaleway**: Beter voor expliciete GDPR/ISO-27001 certificering — overweeg als compliance auditors dat eisen
- **OVH**: Enterprise-grade, duurder
- **AWS/Azure**: Compliance-vriendelijker maar 3-5x duurder
**Conclusie**: Hetzner voor nu, Scaleway als backup als auditors expliciete certificering vragen.
### Valkey i.p.v. Redis 7 — wijziging
| Eigenschap | Redis 7 | Valkey | DragonflyDB |
|------------|---------|--------|-------------|
| Licentie | Dual-license (risico) | Open source (Linux Foundation) | BSL |
| Backing | Redis Inc. | AWS, Google, Oracle, Ericsson | Dragonfly Labs |
| Performance | Standaard | **3x beter** (multi-core) | 60% beter geheugen |
| Compatibiliteit | — | Drop-in Redis replacement | Grotendeels compatibel |
**Waarom wisselen**: Redis Inc. heeft licentiewijzigingen doorgevoerd. Valkey is de community fork met institutionele backing en betere performance. 100% Redis-compatible.
### node-redis i.p.v. ioredis — wijziging
| Eigenschap | ioredis | node-redis |
|------------|---------|------------|
| npm downloads/week | 9.97M | 6.27M |
| Status | **Deprecated** | Actief onderhouden door Redis Inc. |
| Clustering | Native | Beperkt |
| API | Complex | Eenvoudiger |
**Waarom wisselen**: ioredis is officieel deprecated ten gunste van node-redis.
**Let op**: BullMQ gebruikt ioredis intern. Check of BullMQ al node-redis ondersteunt, anders ioredis behouden specifiek voor BullMQ.
### BullMQ 5.69 — behouden
| Eigenschap | BullMQ | pg-boss | Quirrel |
|------------|--------|---------|---------|
| Versie | 5.69.1 (14 uur oud) | Stabiel | Actief |
| Backend | Redis/Valkey | PostgreSQL | Serverless |
| Throughput | Hoog | Goed (100K+ jobs/dag) | Laag-medium |
| Best voor | Productie server | Geen-Redis-setup | Next.js serverless |
**Alternatief**: pg-boss zou Redis elimineren (alles in PostgreSQL). Maar we hebben Redis/Valkey toch al nodig voor caching (C37). BullMQ is de betere keuze.
### Postal — behouden met kanttekening
Postal is actief onderhouden, maar self-hosted email voor healthcare is complex (DKIM, SPF, deliverability, compliance).
**Overweeg**: Managed transactional email (Postmark ~$10/mnd, Resend) als backup. Compliance is makkelijker met managed providers.
### Pino 10.3 — behouden
| Eigenschap | Pino | Winston | Bunyan |
|------------|------|---------|--------|
| npm downloads/week | 17.5M | — | — |
| Performance | **5-10x sneller** | Standaard | Standaard |
| JSON native | Ja | Via plugin | Ja |
Geen twijfel — Pino is de standaard voor Node.js structured logging.
### OpenTelemetry Node.js SDK 2.x — behouden
Productie-klaar sinds 2025. Aanbevolen backend stack:
```
App → OpenTelemetry SDK → (optioneel) OTel Collector
Grafana Tempo (traces)
Prometheus (metrics)
Grafana Loki (logs)
Grafana (dashboard)
```
Alles self-hosted, open source.
### Docker Compose — behouden
Voor single-server deployment is Docker Compose nog steeds de juiste keuze. Docker Swarm is stagnant (geen actieve ontwikkeling sinds 2019). K3s is overkill voor één server.
---
## 5. Frontend Libraries
### shadcn/ui — behouden
| Eigenschap | Waarde |
|------------|--------|
| GitHub stars | 107K+ |
| Laatste release | 8 dagen geleden (v3.8.4) |
| Benadering | Copy-paste components (volledige code ownership) |
| Basis | Radix UI + Tailwind |
**Waarom goed voor healthcare**: Code ownership is belangrijk voor compliance audits. Volledig toegankelijk (WCAG via Radix UI).
### Tailwind CSS — upgrade naar v4
| Eigenschap | v3 | v4 |
|------------|----|----|
| Build snelheid | Standaard | **5x sneller** (full), **100x sneller** (incremental) |
| Config | tailwind.config.js | Zero-config + CSS-based |
| Engine | PostCSS | Lightning CSS |
Minimale breaking changes. Upgrade is laag risico, hoge winst.
### Zustand 5.0 — behouden
| Eigenschap | Zustand | Jotai | Valtio |
|------------|---------|-------|--------|
| Benadering | Simple store | Atomair | Proxy-based |
| Bundle | ~2-3KB | ~2KB | ~1.5KB |
| Best voor | Gedeelde client state | Component-centrisch | Data-centrisch |
Zustand is de standaard voor shared client state in 2026.
### Zod 4.3 — behouden
44M+ downloads/week, mature ecosysteem. **Valibot** (1.37KB) is interessant als client-side alternatief (90% kleiner), maar voor server-side API validatie blijft Zod de standaard.
### date-fns 4.1 — behouden
35M+ downloads/week. Nederlandse locale ondersteuning. Temporal API is nog Stage 3 — niet beschikbaar in alle browsers. date-fns blijft nodig.
### Fuse.js 7.1 — behouden
Voldoende voor fuzzy search op patiëntnamen. **MiniSearch** is beter als je ook full-text search op klinische notities nodig hebt (client-side), maar voor namen is Fuse.js prima.
### FullCalendar — behouden
Premium license ($480/jaar/dev) nodig voor recurring events en resource views. **React Big Calendar** (gratis, MIT) als budget krap is. **Schedule-X** als modern open-source alternatief.
### Lucide React 0.564 — behouden
Actief onderhouden (release gisteren), 9.9K+ projecten, tree-shakeable. Geen reden om te wisselen.
### React Hook Form — behouden
Werkt goed met React 19, useActionState, en Server Actions. **Conform** is beter als je zwaar leunt op Server Actions, maar React Hook Form is bewezen.
---
## 6. AI & Spraak
### Vercel AI SDK i.p.v. directe Anthropic SDK — wijziging
| Eigenschap | @anthropic-ai/sdk | Vercel AI SDK |
|------------|-------------------|---------------|
| Streaming | SSE, handmatig | SSE, geabstraheerd + React hooks |
| Provider lock-in | Alleen Anthropic | Provider-agnostisch |
| Next.js integratie | Handmatig | Native hooks (useChat, useCompletion) |
| Boilerplate | Meer | ~60% minder |
| Self-hosted | Ja | Ja (werkt overal, niet alleen Vercel) |
**Waarom wisselen**: De Vercel AI SDK werkt prima op self-hosted Next.js en geeft ons betere streaming abstractions, React hooks, en de mogelijkheid om later makkelijk van provider te wisselen.
### Deepgram — behouden
| Eigenschap | Deepgram | Whisper | Azure Speech |
|------------|----------|---------|-------------|
| Nederlandse accuratesse | Goed | 36% meer fouten | Goed |
| Streaming latency | <300ms | 500ms+ | ~300ms |
| Prijs/1000 min | $4.30 | $6.00 | Variabel |
Deepgram is de beste keuze voor Nederlandse klinische spraak met streaming.
### pgvector voor RAG — behouden
Voldoende voor 100K documenten. Geen extra infra nodig.
### Embeddings — nieuw: MedRoBERTa.nl
**Belangrijke vinding**: Er bestaat een **MedRoBERTa.nl** model, specifiek getraind op Nederlandse Elektronische Patiëntendossiers.
| Model | Taal | Domein | Best voor |
|-------|------|--------|-----------|
| MedRoBERTa.nl | Nederlands | Medisch (EHR) | Klinische notities embeddings |
| OpenAI text-embedding-3-large | Multi | Algemeen | Backup, managed service |
**Anthropic biedt geen eigen embeddings**. Partner is Voyage AI.
**Aanbeveling**: MedRoBERTa.nl als primary embedding model voor de RAG pipeline. OpenAI als fallback.
---
## 7. Compatibiliteitsmatrix — Werkt alles samen?
```
Node.js 22 LTS ─────────────────────────────────────────────────
├── Next.js 16.1 LTS ──── React 19 ──── TypeScript 5.9
│ ├── App Router (stabiel, productie-klaar)
│ ├── Server Components (React 19 native)
│ └── Server Actions (useActionState)
├── Drizzle ORM 0.45 ──── PostgreSQL 17 (Docker)
│ ├── pgvector 0.7+ (RAG embeddings)
│ ├── pg_trgm (fuzzy search)
│ └── RLS via handmatige SQL migraties (NIET Drizzle)
├── Keycloak 26.5 ──── Auth.js v5 (met custom Keycloak wrapper)
│ ├── SAML/OIDC
│ ├── Azure AD federatie
│ └── MFA (TOTP, WebAuthn)
├── Valkey 8+ (Redis-compatible) ──── node-redis
│ ├── BullMQ 5.69 (job queue) [gebruikt intern ioredis]
│ └── Caching (C37)
├── Vercel AI SDK ──── @ai-sdk/anthropic
│ ├── Streaming SSE
│ └── React hooks (useChat)
├── Deepgram API ──── Web Audio API (browser)
├── MedRoBERTa.nl ──── pgvector (embeddings → vector search)
├── Tailwind CSS 4.x ──── shadcn/ui 3.8+
│ └── Lucide React 0.564
├── Zustand 5.0 (client state)
├── Zod 4.3 (validatie)
├── date-fns 4.1 (NL locale)
├── Fuse.js 7.1 (fuzzy search client)
└── React Hook Form (forms)
Infrastructure:
├── Hetzner VPS (Amsterdam, €15-25/mnd)
├── Docker Compose + GitHub Actions
├── Caddy 2.10 (reverse proxy, auto-HTTPS)
├── Pino 10.3 → Grafana Loki
├── OpenTelemetry 2.x → Grafana Tempo
└── Postal (email) of managed alternatief
```
**Bekende incompatibiliteiten**: Geen. Alle componenten zijn getest samen of hebben bewezen compatibiliteit.
**Enige aandachtspunt**: BullMQ gebruikt intern ioredis. Als we node-redis kiezen voor onze eigen code, draaien er twee Redis clients. Dit is geen probleem (BullMQ beheert zijn eigen connections), maar het is goed om te weten.
---
## 8. Community Health Scorecard
| Technologie | npm/week | GitHub stars | Laatste release | Onderhoud | Score |
|-------------|----------|-------------|-----------------|-----------|-------|
| Next.js 16 | 14.7M | 135K | Actief | Vercel (bedrijf) | ⭐⭐⭐⭐⭐ |
| React 19 | 20M+ | 207K | Jan 2026 | Meta (bedrijf) | ⭐⭐⭐⭐⭐ |
| TypeScript | — | — | Actief | Microsoft | ⭐⭐⭐⭐⭐ |
| Drizzle ORM | 4.7M | 32.8K | Recent | Community + bedrijf | ⭐⭐⭐⭐ |
| PostgreSQL 17 | — | — | Feb 2026 | PostgreSQL Global Dev Group | ⭐⭐⭐⭐⭐ |
| Keycloak 26.5 | — | — | Feb 2026 | Red Hat | ⭐⭐⭐⭐⭐ |
| Auth.js v5 | — | — | Actief | Community | ⭐⭐⭐ |
| BullMQ 5.69 | — | — | 14 uur geleden | Taskforce.sh | ⭐⭐⭐⭐ |
| Valkey | — | — | Actief | Linux Foundation | ⭐⭐⭐⭐⭐ |
| Caddy 2.10 | — | — | Actief | Community + bedrijf | ⭐⭐⭐⭐ |
| Pino 10.3 | 17.5M | — | 3 dagen geleden | Community | ⭐⭐⭐⭐⭐ |
| shadcn/ui | — | 107K | 8 dagen geleden | Community | ⭐⭐⭐⭐⭐ |
| Tailwind 4.1 | — | — | Actief | Tailwind Labs | ⭐⭐⭐⭐⭐ |
| Zustand 5.0 | — | — | 14 dagen geleden | pmndrs collective | ⭐⭐⭐⭐ |
| Zod 4.3 | 44M | 41.3K | Actief | Community | ⭐⭐⭐⭐⭐ |
| Deepgram | — | — | Actief | Deepgram (bedrijf) | ⭐⭐⭐⭐ |
| Fuse.js 7.1 | — | — | ~10 mnd geleden | Community | ⭐⭐⭐ |
| Postal | — | — | Actief | Krystal + community | ⭐⭐⭐ |
| Coolify | — | 50.2K | Jan 2026 | Community | ⭐⭐⭐ (beta) |
---
## 9. Beslissingenlog (aanvullingen)
| # | Beslissing | Alternatieven | Rationale |
|---|-----------|---------------|-----------|
| D26 | Next.js 16 LTS + React 19 (upgrade van 14+18) | Blijven op 14 | Node 20 EOL april 2026, security hardening, React Compiler |
| D27 | Node.js 22 LTS | Blijven op 20 | Node 20 EOL in 2 maanden |
| D28 | Valkey i.p.v. Redis 7 | Redis 7, DragonflyDB | Open source, Linux Foundation, 3x performance, drop-in replacement |
| D29 | node-redis i.p.v. ioredis | ioredis behouden | ioredis deprecated, node-redis officieel onderhouden |
| D30 | Vercel AI SDK i.p.v. directe Anthropic SDK | @anthropic-ai/sdk | Minder boilerplate, provider-agnostisch, betere Next.js integratie |
| D31 | MedRoBERTa.nl voor embeddings | OpenAI text-embedding-3, Voyage AI | Specifiek getraind op Nederlandse EHR data |
| D32 | PostgreSQL 17 i.p.v. 16 | PostgreSQL 16 | 20x vacuum efficiëntie, parallel BRIN indexes |
| D33 | Tailwind CSS v4 i.p.v. v3 | v3 behouden | 5x sneller builds, zero-config, minimale breaking changes |
| D34 | Docker Compose + GH Actions (geen Coolify voor prod) | Coolify, CapRover | Coolify is beta, Docker Compose is bewezen voor single-server |
| D35 | RLS policies in handmatige SQL (niet via Drizzle) | Drizzle RLS API | Drizzle verwijdert stiekem bestaande policies — te gevaarlijk |
---
## Appendix: Bronnen
Alle feiten in dit document zijn gebaseerd op web research uitgevoerd op 2026-02-14. Belangrijkste bronnen per categorie:
**Frameworks**: Next.js releases/blog, React.dev versions, Node.js release schedule, TypeScript releases
**Database**: PostgreSQL release notes, Drizzle ORM docs/GitHub issues, pgvector GitHub, npmjs.com
**Auth**: Keycloak releases, Auth.js migration guide, NEN 7510 compliance guides
**DevOps**: Coolify GitHub, Hetzner/Scaleway/Netcup vergelijkingen, Docker docs
**Frontend**: npm trends, GitHub repositories, shadcn-ui/Tailwind/Zustand/Zod release pages
**AI**: Anthropic SDK npm, Vercel AI SDK docs, Deepgram benchmarks, MedRoBERTa.nl research papers