There's something you missed here, and that's environment cleanup.

I suggest the following logic:

* If there are any rows to delete
* Find their environments (`SELECT DISTINCT env FROM events... WHERE date < ?`)
* Delete the rows
* Delete any environments that are both in the set and are no longer used by any events.

I suggest this complicated version to avoid deleting the current environment. An equivalent is this:

```
DELETE FROM environments
WHERE (SELECT COUNT(*) FROM events_view WHERE date >= ? 
       AND events_view.id = environments.id) = 0
AND id IN (SELECT DISTINCT env FROM events_view WHERE date < ?);

DELETE FROM events_integer WHERE date < ?;
```

(though you might want to replace the view reference with a `UNION ALL` to leverage indices.)

This will only work if I remembered to put `ON DELETE CASCADE` in the environments table definition. If I didn't, you'll need to do this in parts.

Extra points if you figure out a way to delete old environments that were never used...