Troubleshooting and Optimizing Next.js 15+ Server Actions on Cloudflare OpenNext/Workers

Next.js 15 and Server Actions have brought massive changes to the React ecosystem. However, running them in an edge environment like Cloudflare Workers rather than Vercel introduces several technical hurdles. Fortunately, deploying Next.js apps to Cloudflare has become much easier thanks to OpenNext.
This post details troubleshooting points and performance optimization methods you might encounter when deploying Server Actions to Cloudflare OpenNext/Workers in a Next.js 15+ environment.
1. Understanding OpenNext and Cloudflare Workers Architecture
While Vercel provides a Node.js environment (or their own Edge runtime), Cloudflare Workers use a unique runtime based on V8 Isolates. Consequently, code that directly relies on Node.js built-in modules (e.g., fs, path, crypto) can trigger errors.
OpenNext converts the Next.js build output into a format that Cloudflare Workers can understand (via an Adapter). However, with Server Actions, subtle bugs caused by runtime differences are likely to occur during form data parsing and returning execution results from the server.
2. Common Deployment Errors and Solutions for Server Actions
2-1. FormData Parsing Errors (Multipart/form-data)
When handling file uploads in Server Actions, multipart/form-data parsing errors often occur. You might hit Cloudflare Workers’ memory limit (128MB) and request size limit (typically 100MB).
Solution: Instead of sending large file uploads directly through Server Actions, you should issue a Presigned URL from Cloudflare R2 and upload directly from the client (Direct Upload).
// app/actions.ts
'use server'
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
const s3 = new S3Client({
region: "auto",
endpoint: process.env.R2_ENDPOINT,
credentials: {
accessKeyId: process.env.R2_ACCESS_KEY_ID!,
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY!,
},
});
export async function getUploadUrl(filename: string, contentType: string) {
const command = new PutObjectCommand({
Bucket: process.env.R2_BUCKET_NAME,
Key: filename,
ContentType: contentType,
});
// Create a URL valid for 60 seconds at the edge
const signedUrl = await getSignedUrl(s3, command, { expiresIn: 60 });
return signedUrl;
}
2-2. Node.js Dependency Errors (Bcrypt, etc.)
Using Node.js native binding libraries like bcrypt for user authentication in Server Actions will cause a crash in the Workers environment.
Solution:
You should use Web Crypto API-supported libraries like bcryptjs (a pure JS implementation), the WASM version of @node-rs/argon2, or cf-workers-hash.
2-3. Database Connection Pool Exhaustion
Server Actions are executed per request. If you connect directly (TCP) to databases like PostgreSQL, your connections can quickly deplete.
Solution: Use Cloudflare Hyperdrive to manage connection pooling, or use an HTTP-based database service (e.g., Prisma Accelerate, Neon Serverless, Supabase REST).
3. Performance Optimization Tips
3-1. Explicitly Declare the Edge Runtime
If a Server Action is tied to a specific route, explicitly declaring the edge runtime for that route improves performance. OpenNext handles this more efficiently.
export const runtime = 'edge';
3-2. Cache Invalidation using Revalidate
When using revalidatePath or revalidateTag after a Server Action completes, you must understand how OpenNext’s KV-based caching works. Cloudflare KV has Eventual Consistency, so updates can be delayed by up to 60 seconds.
If you need instantaneous cache invalidation, consider configuring Cloudflare D1 or an external Redis (like Upstash) as Next.js’s Custom Cache Handler instead of Workers KV.
Summary
💡 Core Checklist for Server Actions on Cloudflare
- For large files, use R2 Presigned URLs for direct client uploads instead of Server Actions.
- Avoid Node.js native APIs (
fs, C++ Addons) and replace them with Web APIs or pure JS packages.- When connecting to DBs, utilize Hyperdrive or HTTP-based Serverless DBs.
- Be aware of the eventual consistency of Cloudflare Cache/KV when designing around
revalidatePath.
The combination of OpenNext and Cloudflare Workers is a fantastic infrastructure to serve the Next.js ecosystem globally at the lowest cost and highest speed. As long as you are careful with a few minor early configurations, you can fully enjoy the benefits of powerful Server Actions right at the edge.