Migration Guides¶
Running datastore migrations¶
Application imports, Gunicorn workers, readiness checks, and maintenance scripts do not execute datastore migrations. Run them as an explicit one-off operation with the same Howler image and configuration used by the API deployment.
Command¶
poetry run howler-migrate --list
poetry run howler-migrate --all
poetry run howler-migrate --migration-id action-owner-id-to-owner
--migration-id may be repeated. --all selects the complete registered migration set. --timeout (or its
--transport-timeout alias) sets
HWL_DATASTORE_TRANSPORT_TIMEOUT before Elasticsearch datastore modules are imported. There is no generic --force
option: the migration runner's claim protection must not be bypassed.
--list validates and prints the registered IDs without constructing a datastore. Unknown IDs are rejected before an
Elasticsearch connection is opened. Exit status 0 means all selected migrations completed or were already applied;
1 means a migration, Elasticsearch, or datastore-close failure; 2 means invalid command-line input or selection.
Required configuration¶
Use the exact configuration and data namespace used by the API:
- Mount the API's
config.ymlandmappings.yml, or set the sameHWL_CONF_FOLDER. - Set the exact same
HWL_DATASTORE_INDEX_PREFIX. - Provide the same Elasticsearch credential variables and certificate mounts. API-key hosts use
<HOST>_HOST_APIKEY_IDand<HOST>_HOST_APIKEY_SECRET; basic-auth hosts use the corresponding username/password variables. - Set
HWL_CERT_DIRECTORYwhen certificates are mounted outside/etc/howler/certs. - Use
--timeoutorHWL_DATASTORE_TRANSPORT_TIMEOUTfor the transport timeout. The timeout applies before datastore imports and does not replace task polling bounds. - Set
HWL_MIGRATION_STALE_CLAIM_TIMEOUTabove the maximum expected migration duration. The default is four hours.HWL_MIGRATION_WAIT_TIMEOUTandHWL_MIGRATION_POLL_INTERVALcontrol how a process waits for another active claim. HWL_DATASTORE_TASK_POLL_TIMEOUTandHWL_DATASTORE_TASK_POLL_INTERVALbound and pace asynchronous Elasticsearch task polling.
One-off Kubernetes operation¶
Do not add a Helm migration Job or upgrade hook. Create an operator-run Job or pod using the exact REST image repository and tag. Override the image's Gunicorn entrypoint:
apiVersion: batch/v1
kind: Job
metadata:
name: howler-migrate
spec:
backoffLimit: 0
template:
spec:
restartPolicy: Never
containers:
- name: migration
image: cccs/howler-api:<exact-rest-image-tag>
command: ["python", "-m", "howler.external.run_migrations"]
args: ["--all"]
env:
- name: HWL_DATASTORE_INDEX_PREFIX
value: "<same-value-as-rest>"
# Copy the rendered REST deployment's credential and other env entries.
volumeMounts:
- name: conf
mountPath: /etc/howler/conf/
# Mount howler-certs when the REST deployment mounts it.
volumes:
- name: conf
configMap:
name: howler-server-conf
# Copy the optional howler-certs Secret mount from the REST deployment.
The Job must reuse the REST deployment's howler-server-conf ConfigMap, Elasticsearch credential Secret, optional
certificate Secret, relevant environment variables, and index prefix. Copy the rendered deployment settings rather
than relying on a different values path. Inspect Job logs and the migration records in the
<HWL_DATASTORE_INDEX_PREFIX>-migration alias, for example:
kubectl logs job/howler-migrate
curl -s "$ELASTICSEARCH/<prefix>-migration/_search?q=status:running" | jq
curl -s "$ELASTICSEARCH/<prefix>-migration/_doc/action-owner-id-to-owner" | jq
Take an Elasticsearch snapshot and schedule a maintenance window before running the Job. Scale down REST, ingestion, correlation, and other datastore writers. Disable or suspend the REST HPA while the migration runs so it cannot restore writers after they are scaled down. Restore the HPA and workloads only after the command succeeds and the records and logs have been reviewed.
If a process dies while a migration is running, a later invocation waits for an active claim and atomically replaces a stale claim using its version token. The old process cannot mark the replacement claim applied or delete it. Retry the same command after investigating a nonzero exit; do not manually delete a fresh active claim.
Migrating Howler 2.12.0 to 3.0.0¶
This guide will walk you through the process of migrating your Howler installation from version 2.12.0 to 3.0.0. Version 3.0.0 introduces breaking schema changes that require a complete reindexing of your Elasticsearch data.
⚠️ Important Notice¶
This is a BREAKING CHANGE migration that requires complete data reindexing.
- Downtime Required: Your Howler instance will be unavailable during the migration process
- Data Backup: Create full backups of your Elasticsearch cluster before proceeding
What's Changed in 3.0.0¶
Schema Changes¶
Version 3.0.0 introduces several important schema modifications:
- New Long Data Type: Introduction of
odm.Longfor handling large integer values with proper Elasticsearch long datatype mapping - Byte Count Field Migration:
source.bytesanddestination.bytesfields migrated fromIntegertoLongtype - Case-Insensitive Keywords: Analytic and view titles/names migrated to
odm.CaseInsensitiveKeywordfor improved search functionality - Outline Field Changes: Hit outline values migrated from
odm.Texttoodm.Keywordfor better indexing and querying performance
Affected Indexes¶
The following Elasticsearch indexes require reindexing:
analytic- Analytics data with updated (case-insensitive) name/title fieldshit- Hit data with updated byte counts and converting outline fields to keywordsview- View data with updated (case-insensitive) title fields
Pre-Migration Checklist¶
Before starting the migration process, ensure you have:
- Full system backup of your Elasticsearch cluster
- Sufficient disk space (at least 2x current data size)
- Maintenance window scheduled (migration time varies based on data size and cluster performance)
- Admin access to both Howler API and Elasticsearch cluster
Migration Process¶
Step 1: Backup Your Data¶
# Create Elasticsearch snapshot (adjust repository settings as needed)
curl -X PUT "localhost:9200/_snapshot/migration_backup/howler_v2_backup?wait_for_completion=true" -H 'Content-Type: application/json' -d'
{
"indices": "howler-*",
"ignore_unavailable": true,
"include_global_state": false
}'
Step 2: Stop Howler Services¶
You should scale down all API pods to halt ingestion during the reindexing, while maintaining a single pod to trigger the reindexing script. You don't need to run the script from a pod, it's just the easiest way to guarantee connectivity to the elasticsearch cluster.
Step 3: Update Howler to v3¶
Update your images to Howler V3, and use this version to run the reindxing script.
Step 4: Run the Reindexing Script¶
Howler 3.0.0 includes an improved reindexing script that allows selective index reindexing:
# Navigate to the API directory
cd /path/to/howler/api
# Run the reindexing script
python howler/external/reindex_data.py
The script will:
- Display a safety warning and countdown
- Ask for confirmation before proceeding
- Allow you to select which index to reindex
- Show which specific indexes will be affected
- Ask for final confirmation before starting the reindex
Important: Run the script separately for each index type you need to migrate. The recommended order is:
view(typically smallest, good for testing)analytichit(typically largest, do this last)
Step 5: Verify Migration¶
After reindexing each index, verify the migration was successful:
# Check index health
curl -X GET "localhost:9200/_cluster/health?pretty"
# Verify index mappings include new Long type
curl -X GET "localhost:9200/howler-hit-*/_mapping?pretty" | grep -A 5 -B 5 "long"
# Check document counts match expectations
curl -X GET "localhost:9200/howler-*/_count?pretty"
Step 6: Start Howler Services¶
Once all indexes have been successfully reindexed, you can scale the ingestion/api pods back up.
Step 7: Post-Migration Validation¶
Perform the following validation steps:
- API Health Check: Verify the API is responding correctly
curl -X GET "http://your-howler-instance/healthz/"
- Search Functionality: Test search queries to ensure the Howler ODM works with the new schema
- Analytics: Verify that analytics with case-insensitive names work correctly
- Views: Test that view titles are searchable in a case-insensitive manner
- Data Integrity: Spot-check critical data to ensure it migrated correctly
Troubleshooting¶
Common Issues¶
Reindexing Fails with Timeout Error¶
- Increase Elasticsearch timeout settings
- Monitor cluster resources (CPU, memory, disk I/O)
- Consider reindexing during off-peak hours
Insufficient Disk Space¶
- Free up space or add more storage
- Consider temporary deletion of old log files
- Monitor disk usage during reindexing
Memory Issues During Migration¶
- Increase JVM heap size for Elasticsearch
- Reduce concurrent reindexing operations
- Monitor memory usage closely
Index Mapping Conflicts¶
- Verify no custom mappings conflict with new schema
- Check for any manual index modifications
- Ensure clean state before reindexing
Recovery Procedures¶
If migration fails:
- Stop all services immediately
- Restore from backup:
curl -X POST "localhost:9200/_snapshot/migration_backup/howler_v2_backup/_restore"
- Investigate the failure cause
- Plan retry with fixes applied
Migration Time Expectations¶
Production migrations should be expected to take several hours, with the exact duration depending on:
- Cluster Resources: CPU, memory, and disk I/O capacity
- Data Volume: Total size of indexes being reindexed
- Replica Configuration: Number of replicas configured for each index
- Network Performance: Speed between Elasticsearch nodes
- Concurrent Operations: Other activities running on the cluster
Plan for extended maintenance windows and consider scheduling migrations during off-peak hours.
Elasticsearch Version Compatibility¶
No Elasticsearch version upgrade is required for Howler v3.0.0. The schema changes are compatible with your current Elasticsearch installation.
Plugin Compatibility¶
No plugin updates are required. Existing Howler plugins (Sentinel, Evidence, etc.) will continue to work without modification as long as they remain enabled during the migration process.
Configuration Files¶
No configuration file changes are required. This migration only affects the database schema and does not require updates to Howler configuration files.
Rollback Procedure¶
If you need to revert to Howler v2.12.0 after migration:
Option 1: Restore from Backup (Recommended)¶
- Stop Howler services
- Restore indexes from backup using Elasticsearch's stack management:
curl -X POST "localhost:9200/_snapshot/migration_backup/howler_v2_backup/_restore"
- Revert Howler API to v2.x:
# Docker method
docker pull cccs/howler-api:2.12.0
# Update docker-compose.yml or deployment manifests
- Restart services with v2.12.0
Option 2: Manual Rollback¶
If you cannot restore from backup, you'll need to:
- Manually recreate the old schema mappings
- Re-migrate the data back to the old field types
- This is significantly more complex and time-consuming
Always prefer Option 1 - maintain good backups before migration.
API Compatibility¶
No API endpoint changes are included in this migration. This is a database-only change that does not affect:
- REST API endpoints
- Request/response formats
- Authentication mechanisms
- Client application integrations
Your existing client applications and integrations will continue to work without modification.
Testing Strategy¶
Testing in a staging environment is strongly recommended before production migration.
Staging Environment Setup¶
- Create staging cluster with production-like data volume
- Test the complete migration process using the reindexing script
- Validate application functionality after migration
- Measure migration timing to plan production windows
- Practice rollback procedures to ensure they work correctly
Test Scenarios¶
- Search functionality with new case-insensitive keywords
- Analytics queries involving byte count fields (now Long type)
- Plugin operations to ensure continued compatibility
- Performance testing to identify any query optimization needs
Pre-Production Checklist¶
- Staging migration completed successfully
- Application functionality validated in staging
- Migration timing documented for production planning
- Rollback procedure tested and validated
- Production maintenance window scheduled
- All stakeholders notified of the migration schedule
Summary¶
This migration guide provides a comprehensive approach to upgrading Howler from v2.12.0 to v3.0.0. The key points to remember:
- Plan for several hours of downtime depending on your data size
- Always backup before starting the migration process
- Test in staging first to validate the process and timing
- Use the selective reindexing script to migrate indexes one at a time
- Monitor closely during and after the migration
- Have a rollback plan ready in case of issues
With proper preparation and testing, this migration will provide improved search functionality and better data type handling for large integer values in your Howler deployment.
Migration: Legacy _hot Index to ILM Rollover¶
When ILM is enabled for an index that was previously using the legacy _hot naming convention (e.g. howler-hit_hot),
Howler still performs its separate ILM collection bootstrap when the collection is first constructed. This is not a
datastore data migration and is unrelated to howler-migrate; no registered data migration runs as an API startup side
effect.
What happens automatically¶
When the Howler API starts and _ensure_collection_ilm() runs for a collection, it detects one of three states:
-
ILM indices already exist (pattern
{name}-0*): No action needed. The alias is verified and the collection is ready. -
Legacy
_hotindex exists (e.g.howler-hit_hot): Automatic migration: - The ILM policy and composable index template are created/updated.
- Writes to the old
_hotindex are temporarily blocked. - The
_hotindex is cloned to{name}-000001(e.g.howler-hit-000001). - ILM lifecycle settings (
lifecycle.name,lifecycle.rollover_alias) are applied to the new index. - The alias (
howler-hit) is atomically swapped: the old_hotindex is removed from the alias, and the new-000001index is added as the write index. - Writes to the old
_hotindex are unblocked (it remains in the cluster until manually removed). -
All data is preserved — the clone is a zero-copy operation at the filesystem level in Elasticsearch.
-
Fresh install (no existing index): A new
{name}-000001index is created with the ILM policy and rollover alias already attached.
What operators should do¶
- Before enabling ILM: No preparation is needed. The migration is safe to run on a live cluster.
- After migration: The old
_hotindex will still exist in the cluster but is no longer referenced by the alias. Operators can delete it at their convenience to reclaim disk space:DELETE /howler-hit_hot - Rollback: If you need to revert, disable
ilm.enabledin the config, manually recreate the alias pointing to_hot, and delete the-000001index. However, any documents written after migration will only be in the new index.
Configuration¶
Enable ILM by adding the following to your Howler configuration:
datastore:
ilm:
enabled: true
rollover_max_age: "30d" # Max age before rollover (default: 30d)
rollover_max_size: "50gb" # Max primary shard size before rollover (default: 50gb)
indices:
hit:
warm: "30d" # Move to warm phase after 30 days
cold: "90d" # Move to cold phase after 90 days
rollover_max_age/rollover_max_size: Triggers for creating a new write index. Whichever threshold is hit first causes the rollover.warm: Optional. Min age before the index transitions to the warm phase (triggers a force-merge). Omit to skip the warm phase.cold: Optional. Min age before the index transitions to the cold phase. Omit to skip the cold phase.- There is no delete phase — the existing retention cronjob handles document deletion via
delete_by_queryacross all tiers using the alias. - There is no readonly action in warm/cold — the retention cronjob needs write access to delete expired documents across all indices.
Interaction with existing features¶
- Retention cronjob: Continues to work unchanged. It runs
delete_by_queryagainst the alias, which fans out across all backing indices (hot, warm, cold). No per-tier awareness is needed. - Search: All queries go through the alias and automatically span all backing indices. No changes to search behavior.
- Ingestion: New documents are written to the current write index via the alias. Rollover is managed by Elasticsearch's ILM.