Skip to main content
Matthew Sanetra

Scheduled deployments on a budget

| Last updated

EDIT: I no longer use, I instead use a custom Cloudflare Worker, which I published here: deploy-worker.

I’m a big fan of Cloudflare Pages. In fact, this page is built in a limited Beta version of their containers that a Cloudflare employee had to manually opt me in to.

I’d really like to schedule a time for when new posts would go live but I don’t want to resort to having a server processing every request and rendering (with caching ofcourse).

Static websites are just cooler!


My solution? Push everything to main and set up a cron job to POST to a Deploy Hook daily.

D-did you just say push to main?


Yep. Breaking prod is not possible with a static website. If the build fails, it just doesn’t get uploaded to the edge.

But to have a cron job you need a server or a Raspberry Pi or something, right?


Nope. I’m too broke for any of that. I’m using

Selectively generating

Scheduling deployments is only half of the problem - we must now make sure scheduled posts aren’t generated until the scheduled date!

I’m using Astro v2 and use the amazing content collections feature, and so I just need to make a wrapper over getCollection("..."):

export async function entries() {
  const all = await getCollection("blog");
  const filtered = all.filter((post) => !ignore(post));

  const posts = => withUpdatedPublishTime(post));

  // Make sure most recent post appears first
  posts.sort((a, b) => -;

  return posts;

where we define whether to ignore based on the post’s date:

function ignore(post: CollectionEntry<"blog">) {
  return > new Date();

That’s… surprisingly easy!


Yep! And now we can even inject the scheduled deployment time! 1

function withUpdatedPublishTime(post: CollectionEntry<"blog">) {
  const date = new Date(;

  // Month index below is 0-indexed, day index is not
  if (date >= new Date(2023, 2, 15, 0, 0, 0, 0)) {
    // Since 2023-03-15, we are initiating deployment at 15:00 UTC,
    // so change post publish date to reflect that.


  return {, data: {, date } };


  • I’m crazy and (for this website) exclusively push to main.
  • Why? Because it literally cannot go wrong.
  • It’s free

— Matthew


  1. At the time of writing this post, the time only shows up on the RSS feed.