Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
NestJS + Prisma2 で歩む RLS の世界
Search
ynaka81
May 20, 2022
Technology
1.3k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
NestJS + Prisma2 で歩む RLS の世界
NestJS meetup Online #2 登壇資料
https://nest-jp.connpass.com/event/244015/
ynaka81
May 20, 2022
Other Decks in Technology
See All in Technology
Oracle Cloud Infrastructure IaaS 新機能アップデート 2026/6 - 2026/8
oracle4engineer
PRO
0
190
Sigmaで作る業務アプリ
kazushiro_honma
0
120
2026_devsumi_ozono.pdf
o3
3
440
enechainの内製セルフサービスプラットフォーム
hiyosi
0
160
Multica × 長期記憶:40個のミニプロジェクト管理
eiei114
1
260
研究開発部の紹介 / Sansan R&D Profile
sansan33
PRO
5
25k
2026-09-10 【Snowflake World Tour Tokyo 2026】dbt Core と Snowflake で実現する多層的なデータガバナンス / Multi-Layered Data Governance Powered by dbt Core and Snowflake
civitaspo
0
360
GoにおけるFFIのこれまでとこれから
goccy
5
2.5k
HRC_Frontend_Conference_Fukuoka_2026.pdf
ts020
0
600
リージョンの壁を越える、 ちょっと変わったAWSサービスの話
falken
PRO
1
310
AI時代、データエンジニアが一番おもろい
genshun9
0
280
AIで仕事のやり方を変える
matsu7874
3
1.1k
Featured
See All Featured
Art, The Web, and Tiny UX
lynnandtonic
304
22k
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
230
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.8k
Practical Orchestrator
shlominoach
191
12k
How Software Deployment tools have changed in the past 20 years
geshan
1
34k
Paper Plane
katiecoart
PRO
3
53k
Between Models and Reality
mayunak
4
450
Product Roadmaps are Hard
iamctodd
55
13k
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
270
Prompt Engineering for Job Search
mfonobong
0
450
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Fashionably flexible responsive web design (full day workshop)
malarkey
408
67k
Transcript
中川 裕太 @ Beatrust SRE NestJS + Prisma2 で歩む RLS
の世界
今日の登壇内容 Today's topic 去年のちょうど今頃に運用を始めた NestJS + Prisma2 による RLS 適用の後日談です
※ 資料に載せているコードは概念的な簡易コードなのでそのままでは動きません
Agenda RLS とは NestJS + Prisma2 による RLS 実装 性能問題
の改善 1 2 3
2020年12月に Beatrust にジョイン 運用がラクにできるように色々と改善したり、セキュリティ 向上したり、インフラ作ったり API 開発したりしています 中川 裕太 Yuta
Nakagawa SRE & Tech Lead @ Beatrust @ynakaSoftTennis 社員インタビュー https://note.com/beatrust/n/n24ac6848907b
Beatrust は、会社や組織のなかで いっしょに働く人のことをもっと知り、助け合い、 そして協業しやすい状態を実現するための タレントコラボレーション プラットフォームです。 Beatrust が提供しているサービス What we
do
創業以来のユーザー数の推移 Growth 2020 年 3 月 Beatrust 創業 2021 年
1 月 1,000 名突破 2021 年 10 月 10,000 名突破 2022 年 3 月 15,000 名突破 2020 年 3 月に創業して以来、 1 年間で 1,000 名、 2 年間で 15,000 名 のユーザーに ご利用をいただいています。 ※ 2020 年 3 月から 2022 年 3 月までに Beatrust に登録された累積ユーザー数です。
導入企業とケーススタディの例 Customer stories すでに日本を代表とする大企業での導入事例があり、実際の従業員による協業・活用事例が生まれています。 普段社内の他部門を支援させていただく仕事を担当 していますが、そうした日常業務の中で、実際に Beatrust が役に立ち始めています。 生産性技術革新部 ビジネスプロセス支援グループ
ご担当者様 自分一人で悶々としているよりは話を聞いてもらっ てアドバイスをもらうことで気持ちを切り替えるこ とが大事だと強く実感できました。 ビジネス開発センター ビジネスインキュベーショ ン ご担当者様 社内にはまだ一度もお会いしたり、仕事をご一緒し たことのない方も多くいらっしゃいますが、少しで も人となりを知ることができ、心構えができて仕事 がしやすくなっています。 事業管理本部FHR・購買部 ご担当者様 国内総合証券会社 不動産デベロッパー コワーキングスペース 大手製薬メーカー 大手通信会社 大手自動車メーカー ほか、数多くの導入・トライアル実績(2022 年 4 月現在) 医療機器メーカー 大手通信機器メーカー 大手広告代理店 システムインテグレーター
RLS とは NestJS + Prisma2 による RLS 実装 性能問題 の改善
1 2 3
Multi-tenant in 1 database 1 tenant in 1 database 1
tenant in 1 instance database structure system cost migration cost security Multi-tenant でのデータベース構成
Multi-tenant in 1 database 1 tenant in 1 database 1
tenant in 1 instance database structure system cost migration cost security コストの観点から multi-tenant in 1 database を採用
アプリケーション側で tenant を WHERE 句で指定する必要がある
ダルいしミスも発生しやすい
そこで Row Level Security (RLS) PostgreSQL NestJS
ALTER TABLE "User" ENABLE ROW LEVEL SECURITY; CREATE POLICY "UserIsolationPolicy"
ON "User" USING ( "tenantId" = current_setting('app.current_tenant') ); 事前に table 単位でデータアクセスに対するポリシーを定義 PostgreSQL NestJS
実行時設定パラメータ に tenant id を指定 SET app.current_tenant = {tenant_id}; PostgreSQL
NestJS
事前定義したポリシーが正になるデータだけ取得 PostgreSQL NestJS User WHERE "tenantId" = current_setting('app.current_tenant')
アプリケーション側だけでなく DB レイヤーである種の WHERE 句をかけられる
tenant を指定しないとデータ取得できないので fail safe な作りになる
RLS とは 性能問題 の改善 1 3 NestJS + Prisma2 による
RLS 実装 2
リクエストごとに独立したコネクションを張り tenant id を設定する PostgreSQL NestJS Client Side Prisma 2
tenant 情報をリクエストの JWT から取得 PostgreSQL NestJS Client Side Prisma 2
tenant in JWT
新規にコネクションを張り tenant id を設定 PostgreSQL NestJS Client Side Prisma 2
SET app.current_tenant = {tenant_id};
tenant id に従ったデータを取得 PostgreSQL NestJS Client Side Prisma 2 User
WHERE "tenantId" = current_setting('app.current_tenant')
Client にデータを返すと同時にコネクションをクローズ PostgreSQL NestJS Client Side Prisma 2 User data
Close connection
これをどう NestJS + Prisma 2 で実装しているか
PostgreSQL NestJS Client Side Prisma 2 MW NestJS の Middleware
と Interceptor で実装 Interceptor
PostgreSQL NestJS Client Side Prisma 2 MW Middleware で Request
Scope の ContextService に情報を格納 Interceptor this.contextService.set('tenantId', jwt.tenantId)
PostgreSQL NestJS Client Side Prisma 2 MW Prisma 2 の
Middleware を使って各クエリの前に SET を実行 Interceptor @Injectable({ scope: Scope.REQUEST }) export class PrismaService extends PrismaClient { constructor(private readonly contextService: ContextService) { this.$use(async (params, next) => { const tenantId = this.contextService.get('tenantId'); await this.$executeRaw(`SET app.current_tenant='${tenantId}';`); return next(params); }); } }
PostgreSQL NestJS Client Side Prisma 2 MW 最後に Interceptor でコネクションをクローズする
Interceptor @Injectable({ scope: Scope.REQUEST }) export class PrismaInterceptor implements NestInterceptor { intercept(context: ExecutionContext, next: CallHandler<any>): Observable<any> { return next.handle().pipe( finalize(() => this.prisma.$disconnect()) ); } }
RLS とは NestJS + Prisma2 による RLS 実装 1 2
性能問題 の改善 3
RLS 適用してから数ヶ月は順調に運用できていました
が
次第に明らかになる性能問題...
アクセスが集中すると異常に遅くなる
何が起きていたのか PostgreSQL NestJS Client Side Prisma 2
コネクションを張る度に Query Engine のプロセスが立ち上がる PostgreSQL NestJS Client Side Prisma 2
Query Engine ※ Prisma 3 ならデフォルトで Node-API Library として動作するので問題化はしない可能性は高いです
プロセスなので当然実行時間は遅く全体に対して支配的 PostgreSQL NestJS Client Side Prisma 2 Query Engine <
100msec > 500msec
そこで
Query Engine でちゃんとコネクションプーリングするように変更 PostgreSQL NestJS Client Side Prisma 2 Query
Engine
つまり
Prisma 2 の Client をグローバルなシングルトンとして実装 PostgreSQL NestJS Client Side Global
Prisma 2 Query Engine MW Req Prisma 2
Request Scope の Client はメソッドをパススルー + RLS PostgreSQL NestJS Client
Side Global Prisma 2 Query Engine MW Req Prisma 2 constructor(conf?: RlsConfig) { this.user.findUnique = this._rebuildQueryMethod( client.user.findUnique ); } private _rebuildQueryMethod(method: Function) { return (client .$transaction([ this.$executeRaw( `SET app.current_tenant='${tenantId}';` ), Reflect.apply(method, client, args), this.$executeRaw( `SET app.current_tenant='';` ), ]) .then((results) => results[1])); };
tenant 情報は同様に Middleware で JWT から取得 PostgreSQL NestJS Client Side
Global Prisma 2 Query Engine MW Req Prisma 2 this.contextService.set('tenantId', jwt.tenantId)
10倍近い latency の改善
まとめ Today's summary NestJS の Request Scope を使うことで リクエストごとのRLS を実装しセキュアなデータ操作を実現
2 3 1 性能問題は発生したが Prisma 2 が推奨するグローバルなシングルトンを作ることで解決 ちょっと強引な方法でも フレームワークの思想にそった実装をするのが大事
Beatrust on note Beatrust techBlog Beatrust のオフィシャルメディア Our official media
Twitter @jp_beatrust Facebook LinkedIn note.com/beatrust 社員のバックグラウンドや、 働き方に関する記事をアップデート しています。 tech.beatrust.com Beatrust の開発者チームによる取り 組みと技術に込めた想いを掲載して いる開発者ブログです。 Beatrust のメンバーに関する記事、開発メンバーの取り組み、最新ニュースリリースなどを随時更新しています。 facebook.com/beatrust.official linkedin.com/company/beatrust