0Pricing
MongoDB Academy · 강의

예약된 트리거와 Cron 작업

학습자는 cron 표현식을 사용한 예약된 트리거를 구성해 오래된 문서 보관과 같은 정기적인 유지 관리 작업을 실행합니다.

예약된 트리거와 Cron 작업은(는) CoddyKit의 무료 MongoDB Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 MongoDB Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. MongoDB Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.

What Are Scheduled Triggers?

Scheduled Triggers in Atlas App Services execute an Atlas Function on a recurring schedule defined by a cron expression. Unlike database triggers (which fire in response to data changes), scheduled triggers fire based on time — making them ideal for maintenance tasks, periodic reports, data archiving, and cache refreshes that need to run automatically without human intervention.

Cron Expression Syntax

Atlas scheduled triggers use standard five-field cron expressions: minute hour day-of-month month day-of-week. Use * for 'every', */n for 'every n units', comma-separated values for lists, and ranges with -. Examples: 0 * * * * = every hour on the hour; 0 2 * * * = daily at 2 AM; */15 * * * * = every 15 minutes.

// Common cron expressions
'0 * * * *'    // Every hour at minute 0
'0 2 * * *'    // Daily at 02:00 UTC
'0 0 * * 0'    // Every Sunday at midnight
'0 0 1 * *'    // First day of every month at midnight
'*/15 * * * *' // Every 15 minutes
'0 9-17 * * 1-5' // Every hour, 9 AM to 5 PM, weekdays

Creating a Scheduled Trigger

You create scheduled triggers in the Atlas UI under App Services > Triggers > Add Trigger > Scheduled. You give it a name, set the schedule (cron expression or preset intervals like 'every 5 minutes'), and link an Atlas Function. The function receives no arguments — it is called with no event payload, unlike a database trigger, so it must know what to do based on the current time.

// Scheduled trigger config (via App Services API)
// {
//   name: 'dailyArchiveJob',
//   type: 'SCHEDULED',
//   config: {
//     schedule: '0 3 * * *'   // 3 AM UTC daily
//   },
//   functionName: 'archiveOldOrders'
// }

Common Use Case: Data Archiving

A classic scheduled trigger use case is archiving documents that are older than a threshold. The function queries for documents beyond the cutoff, copies them to an archive collection (or exports them to S3), then deletes the originals. This keeps the active collection lean and fast without requiring TTL indexes (which delete permanently without archiving).

// Atlas Function: archiveOldOrders (runs at 3 AM daily)
exports = async function() {
  const db = context.services.get('mongodb-atlas').db('mydb')
  const cutoff = new Date()
  cutoff.setMonth(cutoff.getMonth() - 6)  // older than 6 months

  const oldOrders = await db.collection('orders').find({
    createdAt: { $lt: cutoff },
    status: 'completed'
  }).toArray()

  if (oldOrders.length === 0) return

  // Copy to archive, then delete from active collection
  await db.collection('orders_archive').insertMany(oldOrders)
  await db.collection('orders').deleteMany({
    createdAt: { $lt: cutoff }, status: 'completed'
  })

  console.log('Archived ' + oldOrders.length + ' orders')
}

Common Use Case: Aggregating Statistics

Scheduled triggers are perfect for pre-computing expensive aggregations into a summary collection. Instead of running a heavy aggregation on every dashboard request, a scheduled trigger runs the aggregation once per hour (or per day) and stores results in a stats collection. Dashboard queries become instant point-lookups instead of multi-second scans.

// Atlas Function: computeDailyRevenue
exports = async function() {
  const db = context.services.get('mongodb-atlas').db('mydb')
  const today = new Date().toISOString().split('T')[0]  // 'YYYY-MM-DD'

  const result = await db.collection('orders').aggregate([
    { $match: { date: today, status: 'completed' } },
    { $group: { _id: '$region', revenue: { $sum: '$amount' }, count: { $sum: 1 } } }
  ]).toArray()

  // Upsert into stats collection
  for (const row of result) {
    await db.collection('daily_revenue').updateOne(
      { date: today, region: row._id },
      { $set: { revenue: row.revenue, count: row.count } },
      { upsert: true }
    )
  }
}

Common Use Case: Sending Reminders

Scheduled triggers are the right tool for time-triggered notifications: send a reminder email to users who have items in their cart for more than 24 hours, notify users of expiring subscriptions 7 days before renewal, or ping team members about overdue tasks. The trigger runs every hour (or every minute for time-sensitive notifications) and finds documents that meet the threshold.

// Atlas Function: sendCartAbandonmentReminders (runs hourly)
exports = async function() {
  const db = context.services.get('mongodb-atlas').db('mydb')
  const twentyFourHoursAgo = new Date(Date.now() - 24 * 60 * 60 * 1000)

  const abandonedCarts = await db.collection('carts').find({
    updatedAt: { $lt: twentyFourHoursAgo },
    reminderSent: { $ne: true },
    status: 'active'
  }).toArray()

  for (const cart of abandonedCarts) {
    // Send email via a linked external service
    await context.functions.execute('sendEmail', cart.userEmail, 'You left items in your cart!')
    // Mark reminder sent to avoid duplicate emails
    await db.collection('carts').updateOne(
      { _id: cart._id },
      { $set: { reminderSent: true } }
    )
  }
}

Execution Timeout and Long-Running Jobs

Atlas Functions have a maximum execution time of 90 seconds. For long-running jobs (archiving millions of documents, sending thousands of emails), process data in batches: use limit() to process a manageable chunk per invocation, and run the trigger frequently enough to keep up. Use a state document in MongoDB to track the last processed position between invocations.

// Batch processing with state tracking
exports = async function() {
  const db = context.services.get('mongodb-atlas').db('mydb')
  const state = await db.collection('_trigger_state').findOne({ _id: 'archiver' })
  const lastId = state ? state.lastProcessedId : null

  const query = lastId ? { _id: { $gt: lastId }, status: 'completed' } : { status: 'completed' }
  const batch = await db.collection('orders').find(query)
    .sort({ _id: 1 }).limit(500).toArray()

  if (batch.length === 0) return

  await db.collection('orders_archive').insertMany(batch)
  await db.collection('orders').deleteMany({ _id: { $in: batch.map(d => d._id) } })
  await db.collection('_trigger_state').updateOne(
    { _id: 'archiver' },
    { $set: { lastProcessedId: batch[batch.length - 1]._id } },
    { upsert: true }
  )
}

Disabling Triggers During Maintenance

You can temporarily disable a scheduled trigger without deleting it — useful during database migrations, large data imports, or maintenance windows. Disabled triggers do not execute even when their cron schedule fires. Re-enable them after maintenance completes. All configuration is preserved when disabled.

// Disable a trigger via Atlas Admin API
// PUT /api/admin/v3.0/groups/{groupId}/apps/{appId}/triggers/{triggerId}
// Body: { 'disabled': true }

// Via Atlas CLI:
// atlas functions triggers update --triggerId <id> --disabled true

Logging and Monitoring Scheduled Triggers

Every scheduled trigger invocation is logged in the App Services execution log with the status (success/failure/timeout) and any console output from the function (console.log() calls appear in the log). Use structured logging — log the number of documents processed, any errors, and timing — so you can monitor job health and set up Atlas Alerts when a job fails.

// Good logging practice in a scheduled function
exports = async function() {
  const start = Date.now()
  try {
    const db = context.services.get('mongodb-atlas').db('mydb')
    const n = await doWork(db)
    console.log(JSON.stringify({ job: 'archive', status: 'success', processed: n, ms: Date.now() - start }))
  } catch(err) {
    console.error(JSON.stringify({ job: 'archive', status: 'error', error: err.message }))
    throw err  // re-throw so Atlas marks this invocation as failed
  }
}

Scheduled Triggers vs TTL Indexes

MongoDB TTL indexes (expireAfterSeconds) also delete old documents automatically but have limitations: they only delete — they cannot archive to another collection or S3. They run approximately every 60 seconds and cannot be paused. Scheduled triggers give you full control: archive instead of delete, run at specific times, batch process, and add custom business logic before removing documents.

// TTL index: simple deletion, no archiving
db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 86400 })

// Scheduled trigger: archive before delete, full control
// - Archive to S3 or another collection
// - Run only at low-traffic hours
// - Skip certain document types based on business rules
// - Send a Slack notification when done

Testing Scheduled Triggers

After creating a scheduled trigger, you can test it immediately from the Atlas UI using the 'Run' button — this invokes the function once without waiting for the next cron fire time. Use this to verify the function works before it runs in production. Check the execution log to see console output and confirm the function completed successfully.

// You can also test the underlying function directly
// via the Atlas Functions editor 'Run' button or CLI:
// appservices function run --name=archiveOldOrders

// Add a DRY RUN mode to your function for safe testing:
exports = async function(dryRun) {
  const isDry = dryRun || context.environment.values.DRY_RUN === 'true'
  const docs = await getDocsToArchive()
  if (!isDry) {
    await archiveDocs(docs)
  }
  console.log((isDry ? '[DRY RUN] Would archive' : 'Archived') + ' ' + docs.length + ' docs')
}

Quick Check

Test your understanding of MongoDB & NoSQL Databases concepts from this lesson.

Lesson Recap

In this lesson you learned: scheduled triggers run Atlas Functions on a cron schedule for periodic maintenance, reporting, and notifications, processing in batches with state tracking is essential for large jobs that exceed the 90-second function timeout, and scheduled triggers offer more control than TTL indexes by enabling archive-before-delete workflows. Next up we explore writing Atlas Functions in JavaScript.

자주 묻는 질문

“예약된 트리거와 Cron 작업” 강의는 무료인가요?

네 — “예약된 트리거와 Cron 작업” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 MongoDB Academy 강의 전체를 잠금 해제할 수 있습니다. MongoDB Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“예약된 트리거와 Cron 작업”에서 뭘 배우나요?

학습자는 cron 표현식을 사용한 예약된 트리거를 구성해 오래된 문서 보관과 같은 정기적인 유지 관리 작업을 실행합니다. 브라우저에서 직접 실행하는 실습 코드로 MongoDB Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

MongoDB Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 MongoDB Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.

“예약된 트리거와 Cron 작업” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 MongoDB Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 MongoDB Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 데이터베이스 트리거: CRUD 이벤트에 반응하기
  2. 예약된 트리거와 Cron 작업
  3. JavaScript로 Atlas Functions 작성하기
  4. 경량 웹훅으로서의 HTTPS 엔드포인트
← MongoDB Academy(으)로 돌아가기