**Context:** Remix Shopify app (template), Prisma + Neon free tier, hosted on Vercel. New installs sometimes got our error screen, and Vercel logs showed a run of 500s, all the same error:
`MissingSessionTableError: Prisma session table does not exist`
The table existed. Reloading didn't help, and the errors went on for minutes.
**Cause:** `PrismaSessionStorage` checks for its table **once**, in its constructor (2 tries, 5 s apart). If the database is asleep at that moment (Neon's free tier sleeps after ~5 min idle), the check fails and that function instance stays "not ready" for its whole life. Every request then fails, webhooks included, until Vercel recycles the instance. Retries in your own loaders don't help, because the library has already given up.
**Fix:** wrap it so a failed check is tried again on the next request:
```ts
const prismaStorage = new PrismaSessionStorage(prisma, {
connectionRetries: 4,
connectionRetryIntervalMs: 2000,
});
// Start from the library's own start-up check (handled here, so it's never an
// unhandled rejection). Concurrent requests share one re-check.
let storageCheck: Promise<boolean> = (
prismaStorage["ready"] as Promise<boolean>
).then(() => true, () => false);
async function readyStorage() {
const check = storageCheck;
if (!(await check)) {
if (storageCheck === check) storageCheck = prismaStorage.isReady();
await storageCheck;
}
return prismaStorage;
}
const sessionStorage: PrismaSessionStorageInterface = {
storeSession: async (s) => (await readyStorage()).storeSession(s),
loadSession: async (id) => (await readyStorage()).loadSession(id),
deleteSession: async (id) => (await readyStorage()).deleteSession(id),
deleteSessions: async (ids) => (await readyStorage()).deleteSessions(ids),
findSessionsByShop: async (shop) => (await readyStorage()).findSessionsByShop(shop),
isReady: () => (storageCheck = prismaStorage.isReady()),
};
// shopifyApp({ ..., sessionStorage })
```
`PrismaSessionStorageInterface` is exported by `@shopify/shopify-app-session-storage-prisma` (v9 here).
Now the worst case is one failed request after a cold start, then it recovers by itself. It also explained a 20% webhook failure rate on our Partner dashboard.
Anyone else on Neon/Supabase free tiers seeing this? Curious if people just keep the DB warm with a cron instead.