Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

App Automator 🕒

Automatically start and stop your Databricks Apps on a schedule.

Databricks Apps bill for compute while they're running. If you have apps that only need to be up during business hours, App Automator turns them on in the morning and off at night — automatically — so you don't pay for idle compute overnight and on weekends.

It's a single, tiny Databricks Asset Bundle (DAB) that deploys one serverless job. You list your apps and their hours in a simple YAML file, deploy once, and forget about it.

┌────────────────────┐      every 15 min       ┌──────────────────────┐
│  config/apps.yml   │  ───────────────────▶   │  Serverless job runs │
│  (your schedule)   │                         │  src/reconcile.py    │
└────────────────────┘                         └───────────┬──────────┘
                                                            │ compares "should be on?"
                                                            │ vs actual app state
                                                            ▼
                                          starts / stops your apps via the SDK

Why it's cheap 💸

  • Serverless job — no cluster to leave running. Compute spins up only for the few seconds the check takes.
  • The job does almost nothing most of the time. It wakes up, reads your config, and in the common case makes zero API calls that change anything.
  • Default cadence is every 15 minutes (96 tiny runs/day). Each run is a few seconds of serverless compute. You can make it cheaper still by running less often (see Tuning cost).
  • The savings from stopping idle apps dwarf the cost of running this.

Prerequisites

  1. Databricks CLI v0.230+ installed and configured:
    databricks --version
    databricks auth login --host https://<your-workspace>.cloud.databricks.com -p my-workspace
  2. Serverless compute enabled in your workspace (it is by default in most workspaces).
  3. Permission to start/stop the apps you want to manage (you need CAN_MANAGE on them). By default the job runs as you (the deployer).

Quick start (3 steps)

1. Edit your schedule

Open config/apps.yml and list your apps. Use the app name from databricks apps list (the Name column, not the URL):

settings:
  default_timezone: "America/New_York"

apps:
  - name: my-dashboard-app      # exact name from `databricks apps list`
    start: "08:00"              # turn ON at 8:00 AM
    stop:  "19:00"              # turn OFF at 7:00 PM
    days:  [mon, tue, wed, thu, fri]   # weekdays only (this is the default)

Find your app names with:

databricks apps list -p my-workspace

2. Deploy the bundle

databricks bundle deploy -t dev -p my-workspace

That's it — the job is now live and will reconcile your apps every 15 minutes.

3. (Optional) Run it once, right now

Don't want to wait for the next scheduled run? Trigger it manually:

databricks bundle run app_automator -t dev -p my-workspace

Configuring apps

Everything lives in config/apps.yml. Each app supports:

Field Required Description
name App name exactly as in databricks apps list.
start Time to turn the app on, "HH:MM" 24-hour.
stop Time to turn the app off, "HH:MM" 24-hour.
timezone IANA timezone (e.g. America/Los_Angeles). Defaults to default_timezone.
days Days to run: any of [mon,tue,wed,thu,fri,sat,sun]. Defaults to Mon–Fri.
enabled false to make the automator ignore this app. Defaults to true.

Overnight windows work naturally — if stop is earlier than start, the app stays on through midnight:

  - name: my-overnight-app
    start: "22:00"   # 10 PM
    stop:  "06:00"   # 6 AM next day

Apps you don't list are never touched. App Automator only ever starts or stops apps that appear in this file.

After editing the config, redeploy to push the change:

databricks bundle deploy -t dev -p my-workspace

How it works

The job runs src/reconcile.py, which is idempotent:

  1. Reads config/apps.yml.
  2. For each app, computes whether it should be running right now (based on its start/stop/days/timezone).
  3. Fetches the app's actual compute state via the Databricks SDK.
  4. If they differ, it calls apps.start() or apps.stop(). If they already match, it does nothing.

Because it just re-checks state each run, a missed run or a manual start/stop is self-correcting — the next reconcile brings everything back to your schedule.


Tuning cost

The check cadence is a bundle variable. Run less often to spend less:

# Every 30 minutes instead of 15:
databricks bundle deploy -t dev -p my-workspace \
  --var="reconcile_cron=0 0/30 * * * ?"

# Once an hour, on the hour:
databricks bundle deploy -t dev -p my-workspace \
  --var="reconcile_cron=0 0 * * * ?"

The trade-off: a coarser cadence means an app might turn on/off up to that many minutes late. 15 minutes is a good default.


Testing safely

Dry run — see what the job would do without starting/stopping anything:

databricks bundle deploy -t dev -p my-workspace --var="dry_run=true"
databricks bundle run app_automator -t dev -p my-workspace

Check the run output in the Jobs UI (or the CLI output) — every app will be logged as already ON/OFF or would START/STOP. Set dry_run=false (the default) and redeploy when you're happy.

Run the logic locally (no deploy needed):

pip install -r requirements-dev.txt
python src/reconcile.py --config config/apps.yml --dry-run true -p my-workspace

Unit tests for the schedule math (no Databricks connection needed):

python tests/test_schedule.py

Removing it

Tear down the job completely:

databricks bundle destroy -t dev -p my-workspace

Your apps are left in whatever state they were in — nothing else is affected.


Repository layout

app-automator/
├── databricks.yml              # Bundle definition (name, targets, variables)
├── resources/
│   └── reconcile_job.yml        # The serverless job + schedule
├── src/
│   └── reconcile.py             # The reconcile logic (start/stop apps)
├── config/
│   └── apps.yml                 # 👈 YOU EDIT THIS: your apps + schedules
├── tests/
│   └── test_schedule.py         # Unit tests for the schedule math
├── requirements-dev.txt
├── LICENSE
└── README.md

FAQ

Does this delete or redeploy my apps? No. It only calls start/stop on the app's compute. Your app code and deployment are untouched.

What if an app in my config doesn't exist? It's logged as a NOT FOUND warning and skipped; the run still succeeds and other apps still reconcile. (So the job won't turn red just because of a typo in one app name.)

Who does the job run as? By default, the identity that deployed the bundle. That identity needs CAN_MANAGE on each app it controls.

Can I manage apps across multiple workspaces? Deploy the bundle once per workspace, each with its own config/apps.yml.


License

MIT — see LICENSE.