This is not a very good idea, and there is no need to do this. Just create a [functional index](https://www.postgresql.org/docs/current/static/indexes-expressional.html).

    CREATE INDEX ON table ( ROUND( (ST_Area(geom)/1000)::numeric ,2 ) );

I would create the index on the unrounded version.

    CREATE INDEX ON table ( ST_Area(geom) );

Then a query like this:

    SELECT * ON table WHERE ST_Area(geom) > x;

will use the index. Alternatively, you can create a [`MATERIALIZED VIEW`](https://www.postgresql.org/docs/current/static/rules-materializedviews.html). Generally, it's not a good idea to cache the result of a calculation on the table.

Shy of that, **if you really want to store the computed column on the row your trigger needs to be `BEFORE INSERT OR UPDATE`.** I really wish returning non-null in `AFTER` would generate a warning, but it's [in the docs](https://www.postgresql.org/docs/current/static/plpgsql-trigger.html) (emphasis added):

> The return value of a **row-level trigger fired AFTER** or a statement-level trigger fired BEFORE or AFTER **is always ignored; it might as well be null.** However, any of these types of triggers might still abort the entire operation by raising an error.