Motia Icon
Development Guide

Observability

See what's happening in your Motia app with logging, tracing, and debugging

Your app is running. But what's actually happening inside?

  • Is that API getting hit?
  • Did the message get enqueued?
  • Why did that Step fail?
  • Which user triggered this flow?

Motia gives you everything you need to answer these questions.


Logging

Every Step has a logger in the context. Use it to see what's happening.

Log Levels

LevelWhen to use it
infoNormal stuff - "User created", "Order processed"
warnSomething's weird but not broken - "High API usage", "Slow response"
errorThings broke - Failed API calls, exceptions, crashes
debugDeep debugging - Raw data, internal state, timing info

How to Log

export const handler: Handlers<typeof config> = async (input, { logger }) => {
  logger.info('Processing order')
 
  logger.info('Order created', {
    orderId: input.id,
    total: input.total
  })
 
  try {
    await chargeCard(input.paymentMethod)
  } catch (error) {
    logger.error('Payment failed', {
      error: error.message,
      orderId: input.id
    })
  }
 
  if (input.total > 1000) {
    logger.warn('Large order', {
      total: input.total,
      threshold: 1000
    })
  }
 
  logger.debug('Raw input', { input })
}

Always add context data to your logs. { orderId: '123' } is way more useful than just a message.


Where to See Logs

Start your app:

npm run dev

Logs appear in two places:

1. Your Terminal

See logs right where you ran npm run dev:

[INFO] Processing order { orderId: '123', total: 99.99 }
[INFO] Order created { orderId: '123' }
[INFO] Payment successful

2. The iii Development Console

Open the iii development console and click on your flow. Logs show up in real-time with:

  • Timestamps
  • Which Step logged it
  • The trace ID (to follow a request through the entire flow)
  • Full context data

Tracing

Every request gets a unique traceId. This lets you follow a single request through your entire flow.

export const handler: Handlers<typeof config> = async (req, { logger, traceId, enqueue }) => {
  logger.info('Order started', { traceId })
 
  await enqueue({
    topic: 'process.payment',
    data: { orderId: '123' }
  })
 
  return { status: 200, body: { traceId } }
}

In the iii development console:

  • Click any log entry
  • See all logs with the same traceId
  • Follow the request from start to finish

Debug Mode

Want more detailed logs?

npm run dev -- --debug

This enables debug level logs. You'll see everything - raw inputs, internal state, timing info.

In production: Don't use debug mode (it's slow and logs everything).


Tips for Better Logs

Use Objects, Not Strings

Good:

logger.info('Payment processed', {
  paymentId: '123',
  amount: 100,
  status: 'success'
})

Bad:

logger.info(`Payment 123 processed: amount=100`)

Why? Objects are searchable, filterable, and easier to parse.

Track Performance

export const handler: Handlers<typeof config> = async (input, { logger }) => {
  const start = performance.now()
 
  await processOrder(input)
 
  logger.info('Order processed', {
    duration: performance.now() - start,
    orderId: input.id
  })
}

Log Errors Properly

try {
  await riskyOperation()
} catch (error) {
  logger.error('Operation failed', {
    error: error.message,
    stack: error.stack,
    input: input.id
  })
  throw error
}

Debugging Workflows

Problem: Something's not working, but where?

Steps to debug:

  1. Check terminal logs - See which Steps ran
  2. Open the iii development console at http://localhost:3000
  3. Click your flow - See the visual diagram
  4. Expand logs panel - See all logs in chronological order
  5. Click a log - Filter by that traceId to follow the request
  6. Check each Step - See where it failed

Common Issues

API not responding?

  • Check if the Step ran: Look for logs with your Step's name
  • Check the response: Look for status: 200 in logs

Message not being processed?

  • Check if enqueue() was called: Search logs for "enqueue"
  • Check the topic name: Make sure it matches the queue trigger topic

Step not running?

  • Check if it's discovered: Look for [CREATED] Step in startup logs
  • Check the file name: Must contain .step. or _step

Remember

  • Log everything important - But not everything (no sensitive data!)
  • Use traceId - Follow requests through your entire flow
  • Check the iii development console - Visual debugging is easier
  • Use objects - Don't log strings, log objects
  • Debug mode - Only for development, never in production

On this page