Deploy an Express.js application on Clou·续

This endpoint validates the input, checks the email format, and inserts a new member into the database. It also handles duplicate email addresses by checking for unique constraint violations.

8. Implement update operation

Add an endpoint to update existing members. Add the following route to your src/index.ts file:

src/index.tsts

app.put("/api/members/:id", async (req, res) => {
  try {
    const { id } = req.params;
    const { name, email } = req.body;

// Validate input
    if (!name && !email) {
      return res.status(400).json({
        success: false,
        error: "At least one field (name or email) is required",
      });
    }

// Basic email validation if provided (simplified for tutorial purposes)
    // For production, consider using a validation library or more comprehensive checks
    if (email && (!email.includes("@") || !email.includes("."))) {
      return res.status(400).json({
        success: false,
        error: "Invalid email format",
      });
    }

// Build dynamic update query
    const updates: string[] = [];
    const values: any[] = [];

if (name) {
      updates.push("name = ?");
      values.push(name);
    }
    if (email) {
      updates.push("email = ?");
      values.push(email);
    }

values.push(id);

const result = await env.DB.prepare(
      `UPDATE members SET ${updates.join(", ")} WHERE id = ?`
    )
      .bind(...values)
      .run();

if (result.meta.changes === 0) {
      return res
        .status(404)
        .json({ success: false, error: "Member not found" });
    }

res.json({ success: true, message: "Member updated successfully" });
  } catch (error: any) {
    if (error.message?.includes("UNIQUE constraint failed")) {
      return res.status(409).json({
        success: false,
        error: "Email already exists",
      });
    }
    res.status(500).json({ success: false, error: "Failed to update member" });
  }
});

This endpoint allows updating either the name, email, or both fields of an existing member. It builds a dynamic SQL query based on the provided fields.

9. Implement delete operation

Add an endpoint to delete members. Add the following route to your src/index.ts file:

src/index.tsts

// DELETE - Delete a member
app.delete("/api/members/:id", async (req, res) => {
  try {
    const { id } = req.params;

const result = await env.DB.prepare("DELETE FROM members WHERE id = ?")
      .bind(id)
      .run();

if (result.meta.changes === 0) {
      return res
        .status(404)
        .json({ success: false, error: "Member not found" });
    }

res.json({ success: true, message: "Member deleted successfully" });
  } catch (error) {
    res.status(500).json({ success: false, error: "Failed to delete member" });
  }
});

This endpoint deletes a member by their ID and returns an error if the member does not exist.

10. Test locally

Start the development server to test your API locally:

npm run dev

The development server will start, and you can access your API at http://localhost:8787.

Open a new terminal window and test the endpoints using curl:

Get all memberssh

curl http://localhost:8787/api/members
{
    "success": true,
    "members": [
        {
            "id": 1,
            "name": "Alice Johnson",
            "email": "alice@example.com",
            "joined_date": "2024-01-15"
        },
        {
            "id": 2,
            "name": "Bob Smith",
            "email": "bob@example.com",
            "joined_date": "2024-02-20"
        },
        {
            "id": 3,
            "name": "Carol Williams",
            "email": "carol@example.com",
            "joined_date": "2024-03-10"
        }
    ]
}

Test creating a new member:

Create a membersh

curl -X POST http://localhost:8787/api/members \
  -H "Content-Type: application/json" \
  -d '{"name": "David Brown", "email": "david@example.com"}'
{
    "success": true,
    "message": "Member created successfully",
    "id": 4
}

Test getting a single member:

Get a member by IDsh

curl http://localhost:8787/api/members/1

Test updating a member:

Update a membersh

curl -X PUT http://localhost:8787/api/members/1 \
  -H "Content-Type: application/json" \
  -d '{"name": "Alice Cooper"}'

Test deleting a member:

Delete a membersh

curl -X DELETE http://localhost:8787/api/members/4

11. Deploy to Cloudflare Workers

Before deploying to production, execute the schema file against your remote (production) database:

npx wrangler d1 execute members-db --remote --file=./schemas/schema.sql

Now deploy your application to the Cloudflare network:

npm run deploy
⛅️ wrangler 4.44.0
───────────────────
Total Upload: 1743.64 KiB / gzip: 498.65 KiB
Worker Startup Time: 48 ms
Your Worker has access to the following bindings:
Binding                  Resource
env.DB (members-db)      D1 Database

Uploaded express-d1-app (2.99 sec)
Deployed express-d1-app triggers (5.26 sec)
  https://<your-subdomain>.workers.dev
Current Version ID: <version-id>

After successful deployment, Wrangler will output your Worker's URL.

12. Test production deployment

Test your deployed API using the provided URL. Replace <your-worker-url> with your actual Worker URL:

Test production APIsh

curl https://<your-worker-url>/api/members

You should see the same member data you created in the production database.

Create a new member in production:

Create a member in productionsh

curl -X POST https://<your-worker-url>/api/members \
  -H "Content-Type: application/json" \
  -d '{"name": "Eva Martinez", "email": "eva@example.com"}'

Your Express.js application with D1 database is now running on Cloudflare Workers.

Conclusion

In this tutorial, you built a Members Registry API using Express.js and D1 database, then deployed it to Cloudflare Workers. You implemented full CRUD operations (Create, Read, Update, Delete) and learned how to:

  • Set up an Express.js application for Cloudflare Workers
  • Create and configure a D1 database with bindings
  • Implement database operations using D1's prepared statements
  • Test your API locally and in production

Next steps

Was this helpful?

YesNo

On this page

Deploy an Express.js application on Clou·续 - 图1Docs

{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/workers/tutorials/deploy-an-express-app/#page","headline":"Deploy an Express.js application on Cloudflare Workers","description":"Learn how to deploy an Express.js application on Cloudflare Workers.","url":"https://developers.cloudflare.com/workers/tutorials/deploy-an-express-app/","inLanguage":"en","image":"https://developers.cloudflare.com/workers/tutorials/deploy-an-express-app/og.png?v=9aacd24e06f4a468","dateModified":"2026-08-25","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"},"keywords":["TypeScript"]}


description: This tutorial explains how to programmatically generate a custom YouTube thumbnail using Cloudflare Workers. You may want to customize the thumbnail's design, call-to-actions and images used to encourage more viewers to watch your video. title: Generate YouTube thumbnails with Workers and Cloudflare Image Resizing image: https://developers.cloudflare.com/workers/tutorials/generate-youtube-thumbnails-with-workers-and-images/og.png?v=de5ab2985a819cd9


Skip to content

Documentation Index
Fetch the complete documentation index at: https://developers.cloudflare.com/workers/llms.txt
Use this file to discover all available pages before exploring further.