# SM018: Concurrent operations require atomic = False

**Severity:** ERROR
**Database:** PostgreSQL only
**Category:** indexes, postgresql, high-risk

## Description

PostgreSQL's `AddIndexConcurrently` and `RemoveIndexConcurrently` operations cannot run inside a database transaction. Django migrations are atomic by default (`atomic = True`), which wraps all operations in a transaction.

Using concurrent index operations in an atomic migration will fail with:

```
django.db.utils.OperationalError: CREATE INDEX CONCURRENTLY cannot run inside a transaction block
```

## Examples

### ❌ Incorrect

```python
from django.contrib.postgres.operations import AddIndexConcurrently
from django.db import migrations, models

class Migration(migrations.Migration):
    # atomic = True is the default - concurrent operations will fail!

    operations = [
        AddIndexConcurrently(
            model_name='article',
            index=models.Index(fields=['title'], name='article_title_idx'),
        ),
    ]
```

### ✅ Correct

```python
from django.contrib.postgres.operations import AddIndexConcurrently
from django.db import migrations, models

class Migration(migrations.Migration):
    atomic = False  # Required for concurrent operations

    operations = [
        AddIndexConcurrently(
            model_name='article',
            index=models.Index(fields=['title'], name='article_title_idx'),
        ),
    ]
```

## Why This Matters

1. **Migrations will fail** — Without `atomic = False`, concurrent operations cannot execute
2. **Production deployments break** — This error only appears at runtime, potentially during deployment
3. **Easy to miss** — The migration will appear to work in development if not tested properly

## How to Fix

Add `atomic = False` to your migration class:

```python
class Migration(migrations.Migration):
    atomic = False

    dependencies = [...]
    operations = [...]
```

## Related Rules

- [SM010](SM010.md) — Unsafe index creation (recommends using `AddIndexConcurrently`)
- [SM011](SM011.md) — Unsafe unique constraint (recommends concurrent index approach)

## References

- [Django PostgreSQL specific operations](https://docs.djangoproject.com/en/stable/ref/contrib/postgres/operations/)
- [PostgreSQL CREATE INDEX CONCURRENTLY](https://www.postgresql.org/docs/current/sql-createindex.html#SQL-CREATEINDEX-CONCURRENTLY)
