---
title: "PostgreSQL Query Optimization - Indexes &amp; EXPLAIN ANALYZE"
lang: "en"
author: "Mohammad Abu Mattar"
canonical: https://mkabumattar.com/post/postgresql-query-optimization-indexes-explain
---

![Blog post image for PostgreSQL Query Optimization: Indexes, EXPLAIN ANALYZE & Execution Plans - Master PostgreSQL query optimization with practical examples. Learn EXPLAIN ANALYZE interpretation, effective index strategies, query rewriting, and connection pooling to identify and fix slow queries in production microservices.](/_astro/hero.WD7Zwlat_22N7nk.webp)

[Home](/)›[Codesnippets](/codesnippets)›[All Categories](/codesnippets/categories)›[Database](/codesnippets/categories/database)

Codesnippets

[Prev in DatabaseAWS DynamoDB CRUD Operations in Node.js with the AWS SDK v3](/codesnippets/post/nodejs-dynamodb-crud-aws-sdk-v3)

[Database](/codesnippets/categories/database)[Performance](/codesnippets/categories/performance)[SQL and Python](/codesnippets/sql-and-python)

# PostgreSQL Query Optimization: Indexes, EXPLAIN ANALYZE & Execution Plans

[Mohammad Abu Mattar](/authors/mohammad-abu-mattar)Published: 29 Mar 202605 Mins read04 Mins listen

[Markdown for AI(opens in a new tab)](/post/postgresql-query-optimization-indexes-explain/index.md "Open the plain-Markdown version of this page, for pasting into an AI tool")

TL;DR

Master PostgreSQL query optimization with practical examples. Learn EXPLAIN ANALYZE interpretation, effective index strategies, query rewriting, and connection pooling to identify and fix slow queries in production microservices.

Series

[Database Optimization](/series/database-optimization)1/1

All posts in this series (1)

Code Snippets1

1.  [PostgreSQL Query Optimization: Indexes, EXPLAIN ANALYZE & Execution PlansYou are here](/codesnippets/post/postgresql-query-optimization-indexes-explain)

### PostgreSQL Query Optimization: Indexes, EXPLAIN ANALYZE & Execution Plans

Contents

[Need to optimize slow PostgreSQL queries? Use EXPLAIN ANALYZE and targeted indexing.](#need-to-optimize-slow-postgresql-queries-use-explain-analyze-and-targeted-indexing)[The Problem](#the-problem)[Why queries get slow](#why-queries-get-slow)[Common performance issues](#common-performance-issues)[The Solution](#the-solution)[Reading EXPLAIN ANALYZE](#reading-explain-analyze)[TL;DR](#tldr)[Understanding EXPLAIN ANALYZE](#understanding-explain-analyze)[Basic query analysis](#basic-query-analysis)[Reading the cost](#reading-the-cost)[Creating effective indexes](#creating-effective-indexes)[Basic index creation](#basic-index-creation)[Index types and when to use each](#index-types-and-when-to-use-each)[Partial indexes for common cases](#partial-indexes-for-common-cases)[Multi-column index strategy](#multi-column-index-strategy)[Detecting and fixing N+1 queries](#detecting-and-fixing-n1-queries)[The N+1 problem](#the-n1-problem)[The fix: eager loading](#the-fix-eager-loading)[SQL equivalent](#sql-equivalent)[Finding slow queries automatically](#finding-slow-queries-automatically)[Enable query logging](#enable-query-logging)[Use pg\_stat\_statements](#use-pg_stat_statements)[Query optimization patterns](#query-optimization-patterns)[Pattern 1: missing index on a WHERE clause](#pattern-1-missing-index-on-a-where-clause)[Pattern 2: inefficient subqueries](#pattern-2-inefficient-subqueries)[Pattern 3: functions in WHERE clauses](#pattern-3-functions-in-where-clauses)[Pattern 4: missing ORDER BY index](#pattern-4-missing-order-by-index)[Connection pooling](#connection-pooling)[Why connection pooling matters](#why-connection-pooling-matters)[PgBouncer configuration](#pgbouncer-configuration)[Application connection](#application-connection)[Real-world optimization workflow](#real-world-optimization-workflow)[Step 1: identify the slow query](#step-1-identify-the-slow-query)[Step 2: run EXPLAIN ANALYZE](#step-2-run-explain-analyze)[Step 3: look for expensive operations](#step-3-look-for-expensive-operations)[Step 4: add indexes](#step-4-add-indexes)[Step 5: rerun EXPLAIN ANALYZE](#step-5-rerun-explain-analyze)[Best practices](#best-practices)[1\. Index naming convention](#1-index-naming-convention)[2\. Monitor index usage](#2-monitor-index-usage)[3\. Regular maintenance](#3-regular-maintenance)[Resources](#resources)

### [Need to optimize slow PostgreSQL queries? Use EXPLAIN ANALYZE and targeted indexing.](#need-to-optimize-slow-postgresql-queries-use-explain-analyze-and-targeted-indexing)

Slow database queries kill application performance. Most developers don’t know where the actual bottleneck is, so they guess at fixes. EXPLAIN ANALYZE shows what is expensive and where to optimize.

## [The Problem](#the-problem)

### [Why queries get slow](#why-queries-get-slow)

In development with small datasets, missing indexes don’t matter. Switch to production with millions of rows, and sequential table scans start to cost real time. Queries that ran in 50ms take 5+ seconds. You need to know why.

### [Common performance issues](#common-performance-issues)

-   **Missing indexes**: Forcing full table scans on every query
-   **N+1 queries**: Fetching data in loops instead of bulk operations
-   **Bad query plans**: Using inefficient joins or sorts
-   **Undersized indices**: Index on wrong columns
-   **Connection pool exhaustion**: Running out of available connections

## [The Solution](#the-solution)

### [Reading EXPLAIN ANALYZE](#reading-explain-analyze)

`EXPLAIN ANALYZE` shows exactly how PostgreSQL executes your query, including:

-   Which operations are most expensive (by cost)
-   Actual vs. estimated row counts
-   Time spent in each step
-   Seq Scans vs. Index Scans
-   Sort and Hash operations

### [TL;DR](#tldr)

-   Run EXPLAIN ANALYZE to identify expensive operations
-   Add indexes where sequential scans happen on large tables
-   Use pg\_stat\_statements to automatically find slow queries
-   Fix N+1 query patterns before rewriting complex queries
-   Set up connection pooling so connections get reused instead of reopened

## [Understanding EXPLAIN ANALYZE](#understanding-explain-analyze)

### [Basic query analysis](#basic-query-analysis)

```
1-- Compare these two queries2EXPLAIN ANALYZE3SELECT * FROM users WHERE created_at > '2025-01-01';4
5-- Output example:6-- Seq Scan on users  (cost=0.00..35.50 rows=1000 width=100)7--   Filter: (created_at > '2025-01-01')8--   Planning Time: 0.123 ms9--   Execution Time: 45.234 ms
```

**What this tells you:**

-   `Seq Scan`: Reading entire table (slow for large tables)
-   `cost=0.00..35.50`: PostgreSQL’s estimated cost
-   `rows=1000`: Expected to return 1000 rows
-   `Execution Time: 45.234 ms`: Actual time taken

### [Reading the cost](#reading-the-cost)

```
1EXPLAIN ANALYZE2SELECT u.id, u.name, o.total3FROM users u4LEFT JOIN orders o ON u.id = o.user_id5WHERE u.status = 'active';6
7-- Output:8-- Hash Left Join  (cost=2534.50..5892.33 rows=5000 width=50)9--   Hash Cond: (o.user_id = u.id)10--   ->  Seq Scan on orders o  (cost=0.00..1234.50 rows=50000 width=8)11--   ->  Hash  (cost=2500.00..2500.00 rows=5000 width=42)12--         ->  Index Scan using idx_users_status on users u  (cost=10.00..2500.00 rows=5000 width=42)
```

**Cost interpretation:**

-   Lower cost = faster execution
-   `cost=A..B`: A = startup cost, B = total cost
-   Focus on the highest-cost operations first

## [Creating effective indexes](#creating-effective-indexes)

### [Basic index creation](#basic-index-creation)

```
1-- Simple B-tree index (most common)2CREATE INDEX idx_users_email ON users(email);3
4-- Multi-column index5CREATE INDEX idx_orders_user_date ON orders(user_id, created_at);6
7-- Partial index (only index active users)8CREATE INDEX idx_users_active ON users(id) WHERE status = 'active';9
10-- Unique index (constraint + performance)11CREATE UNIQUE INDEX idx_users_email_unique ON users(email);
```

### [Index types and when to use each](#index-types-and-when-to-use-each)

```
1-- B-tree (default, best for most queries)2CREATE INDEX idx_standard ON table_name(column);3
4-- Hash (equality only, rarely faster than B-tree)5CREATE INDEX idx_hash ON table_name USING hash(column);6
7-- GiST (geometric, full-text search)8CREATE INDEX idx_fulltext ON articles USING gist(search_vector);9
10-- GIN (array, JSON, full-text - faster for large result sets)11CREATE INDEX idx_json ON logs USING gin(metadata);
```

### [Partial indexes for common cases](#partial-indexes-for-common-cases)

```
1-- Don't index inactive records2CREATE INDEX idx_active_orders ON orders(id) WHERE status != 'cancelled';3
4-- Only index recent data5CREATE INDEX idx_recent_events ON events(id) WHERE created_at > NOW() - INTERVAL '90 days';6
7-- Saves space and speeds up queries on active data
```

### [Multi-column index strategy](#multi-column-index-strategy)

```
1-- For WHERE + ORDER BY combinations2-- Query: WHERE user_id = ? ORDER BY created_at DESC3CREATE INDEX idx_user_date ON orders(user_id, created_at DESC);4
5-- Column order matters: Put filtered columns first6-- Good:   WHERE status = ? AND type = ?7CREATE INDEX idx_good ON events(status, type);8
9-- Bad:    WHERE status = ? AND type = ?10CREATE INDEX idx_bad ON events(type, status);  -- Wrong order
```

## [Detecting and fixing N+1 queries](#detecting-and-fixing-n1-queries)

### [The N+1 problem](#the-n1-problem)

```
1# BAD: N+1 queries (1 + N queries)2users = db.query(User).all()  # Query 13for user in users:4    orders = db.query(Order).filter(Order.user_id == user.id).all()  # Queries 2 to N+15    print(f"{user.name}: {len(orders)} orders")6
7# Result with 1000 users = 1001 queries
```

### [The fix: eager loading](#the-fix-eager-loading)

```
1# GOOD: Eager load with join2from sqlalchemy import joinedload3
4users = db.query(User).options(joinedload(User.orders)).all()  # Single query with join5
6for user in users:7    print(f"{user.name}: {len(user.orders)} orders")
```

### [SQL equivalent](#sql-equivalent)

```
1-- BAD (N+1):2SELECT * FROM users;  -- 1000 queries...3SELECT * FROM orders WHERE user_id = ?;4
5-- GOOD (Single query):6SELECT u.id, u.name, o.id, o.total7FROM users u8LEFT JOIN orders o ON u.id = o.user_id;
```

## [Finding slow queries automatically](#finding-slow-queries-automatically)

### [Enable query logging](#enable-query-logging)

```
1-- Enable logging of slow queries (500ms+)2ALTER SYSTEM SET log_min_duration_statement = 500;3SELECT pg_reload_conf();4
5-- View current setting6SHOW log_min_duration_statement;
```

### [Use pg\_stat\_statements](#use-pg_stat_statements)

```
1-- Install extension2CREATE EXTENSION IF NOT EXISTS pg_stat_statements;3
4-- Find slowest queries5SELECT query, calls, mean_time, max_time6FROM pg_stat_statements7ORDER BY mean_time DESC8LIMIT 10;9
10-- Find queries that were called most11SELECT query, calls, mean_time12FROM pg_stat_statements13ORDER BY calls DESC14LIMIT 10;15
16-- Clear stats to get fresh baseline17SELECT pg_stat_statements_reset();
```

## [Query optimization patterns](#query-optimization-patterns)

### [Pattern 1: missing index on a WHERE clause](#pattern-1-missing-index-on-a-where-clause)

```
1-- Before: Seq Scan (slow)2EXPLAIN ANALYZE3SELECT * FROM orders WHERE customer_id = 42;4
5-- Fix: Add index6CREATE INDEX idx_orders_customer ON orders(customer_id);7
8-- After: Index Scan (fast)9EXPLAIN ANALYZE10SELECT * FROM orders WHERE customer_id = 42;
```

### [Pattern 2: inefficient subqueries](#pattern-2-inefficient-subqueries)

```
1-- SLOW: Subquery evaluated for each row2SELECT * FROM orders3WHERE customer_id IN (4  SELECT id FROM customers WHERE status = 'premium'5);6
7-- FAST: Use JOIN instead8SELECT DISTINCT o.*9FROM orders o10JOIN customers c ON o.customer_id = c.id11WHERE c.status = 'premium';
```

### [Pattern 3: functions in WHERE clauses](#pattern-3-functions-in-where-clauses)

```
1-- SLOW: Function applied to indexed column2SELECT * FROM users WHERE LOWER(email) = 'test@example.com';3
4-- FAST: Use expression index5CREATE INDEX idx_users_email_lower ON users(LOWER(email));6SELECT * FROM users WHERE LOWER(email) = 'test@example.com';7
8-- OR: Normalize incoming data instead9SELECT * FROM users WHERE email = 'test@example.com';
```

### [Pattern 4: missing ORDER BY index](#pattern-4-missing-order-by-index)

```
1-- SLOW: Sort step required2EXPLAIN ANALYZE3SELECT * FROM events ORDER BY created_at DESC LIMIT 10;4
5-- Fix: Add index for sort6CREATE INDEX idx_events_date_desc ON events(created_at DESC);7
8-- Now uses Index Scan + Limit, no Sort step
```

## [Connection pooling](#connection-pooling)

### [Why connection pooling matters](#why-connection-pooling-matters)

```
1-- Without pooling: Each request opens/closes connection (expensive)2-- With pooling: Reuse existing connections (cheap)
```

### [PgBouncer configuration](#pgbouncer-configuration)

pgbouncer.ini

```
1[databases]2myapp = host=localhost port=5432 dbname=myapp_prod3
4[pgbouncer]5listen_port = 64326listen_addr = 127.0.0.17auth_type = md58auth_file = /etc/pgbouncer/userlist.txt9
10# Connection pooling settings11pool_mode = transaction12max_client_conn = 100013default_pool_size = 2514min_pool_size = 1015reserve_pool_size = 516reserve_pool_timeout = 3
```

### [Application connection](#application-connection)

```
1# Before pooling: Direct to PostgreSQL2import psycopg23conn = psycopg2.connect("dbname=myapp user=postgres host=localhost")4
5# After pooling: Connect to PgBouncer on port 64326import psycopg27conn = psycopg2.connect("dbname=myapp user=postgres host=localhost port=6432")
```

## [Real-world optimization workflow](#real-world-optimization-workflow)

### [Step 1: identify the slow query](#step-1-identify-the-slow-query)

Terminal window

```
# From application logs or pg_stat_statements# Example: SELECT query is taking 8000ms
```

### [Step 2: run EXPLAIN ANALYZE](#step-2-run-explain-analyze)

```
1EXPLAIN ANALYZE2SELECT o.id, o.total, c.name3FROM orders o4JOIN customers c ON o.customer_id = c.id5WHERE o.created_at > '2025-01-01'6ORDER BY o.total DESC;
```

### [Step 3: look for expensive operations](#step-3-look-for-expensive-operations)

```
1Sort (cost=9234.50..9244.50)  ← Look here2  ->  Hash Join (cost=2500.00..9234.00)  ← And here3        ->  Seq Scan on orders o (cost=0.00..5000.00)  ← Sequential scan on large table4        ->  Hash (cost=100.00..100.00 rows=1000)5              ->  Seq Scan on customers c (cost=0.00..100.00)
```

### [Step 4: add indexes](#step-4-add-indexes)

```
1-- Index for WHERE clause2CREATE INDEX idx_orders_date ON orders(created_at);3
4-- Index for JOIN condition5CREATE INDEX idx_orders_customer_id ON orders(customer_id);6
7-- Index for ORDER BY8CREATE INDEX idx_orders_total ON orders(total DESC);
```

### [Step 5: rerun EXPLAIN ANALYZE](#step-5-rerun-explain-analyze)

```
1-- Should now use Index Scans instead of Seq Scans2-- No Sort step if you have the right index
```

## [Best practices](#best-practices)

### [1\. Index naming convention](#1-index-naming-convention)

```
1-- Consistent naming helps find related indexes2CREATE INDEX idx_table_column_type ON table_name(column);3
4-- Examples:5CREATE INDEX idx_users_email ON users(email);6CREATE INDEX idx_orders_customer_date ON orders(customer_id, created_at);7CREATE INDEX idx_products_active ON products(id) WHERE active = true;
```

### [2\. Monitor index usage](#2-monitor-index-usage)

```
1-- Find unused indexes (bloat)2SELECT schemaname, tablename, indexname3FROM pg_indexes4WHERE schemaname NOT IN ('pg_catalog', 'information_schema');5
6-- Check if index is being used7SELECT8  indexrelname,9  idx_scan,10  idx_tup_read,11  idx_tup_fetch12FROM pg_stat_user_indexes13ORDER BY idx_scan DESC;
```

### [3\. Regular maintenance](#3-regular-maintenance)

```
1-- Analyze table stats (for query planner)2ANALYZE users;3
4-- Vacuum to clean up dead rows5VACUUM FULL users;6
7-- Reindex if fragmented (heavy write workloads)8REINDEX INDEX idx_users_email;
```

## [Resources](#resources)

-   [PostgreSQL EXPLAIN Documentation](https://www.postgresql.org/docs/current/sql-explain.html)
-   [Index Types & When to Use](https://www.postgresql.org/docs/current/indexes-types.html)
-   [Query Planning & Optimization](https://www.postgresql.org/docs/current/planner.html)
-   [pg\_stat\_statements](https://www.postgresql.org/docs/current/pgstatstatements.html)
-   [PgBouncer Connection Pooling](https://www.pgbouncer.org/)

Was this useful?

## Tags

[#PostgreSQL](/codesnippets/tags/postgresql)[#QueryOptimization](/codesnippets/tags/queryoptimization)[#Indexes](/codesnippets/tags/indexes)[#Performance](/codesnippets/tags/performance)[#SQL](/codesnippets/tags/sql)[#Database](/codesnippets/tags/database)[#Microservices](/codesnippets/tags/microservices)

## Share

[Facebook](https://facebook.com/sharer/sharer.php?u=https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fpostgresql-query-optimization-indexes-explain "Share on Facebook")[Twitter](https://twitter.com/intent/tweet/?text=PostgreSQL%20Query%20Optimization%3A%20Indexes%2C%20EXPLAIN%20ANALYZE%20%26%20Execution%20Plans&url=https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fpostgresql-query-optimization-indexes-explain "Share on Twitter")[LinkedIn](https://www.linkedin.com/shareArticle?mini=true&url=https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fpostgresql-query-optimization-indexes-explain&title=PostgreSQL%20Query%20Optimization%3A%20Indexes%2C%20EXPLAIN%20ANALYZE%20%26%20Execution%20Plans&summary=Master%20PostgreSQL%20query%20optimization%20with%20practical%20examples.%20Learn%20EXPLAIN%20ANALYZE%20interpretation%2C%20effective%20index%20strategies%2C%20query%20rewriting%2C%20and%20connection%20pooling%20to%20identify%20and%20fix%20slow%20queries%20in%20production%20microservices.&source=https://mkabumattar.com "Share on LinkedIn")[WhatsApp](https://wa.me/?text=PostgreSQL%20Query%20Optimization%3A%20Indexes%2C%20EXPLAIN%20ANALYZE%20%26%20Execution%20Plans%20https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fpostgresql-query-optimization-indexes-explain "Share on WhatsApp")[Telegram](https://t.me/share/url?url=https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fpostgresql-query-optimization-indexes-explain&text=PostgreSQL%20Query%20Optimization%3A%20Indexes%2C%20EXPLAIN%20ANALYZE%20%26%20Execution%20Plans "Share on Telegram")[Reddit](https://www.reddit.com/submit?url=https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fpostgresql-query-optimization-indexes-explain&title=PostgreSQL%20Query%20Optimization%3A%20Indexes%2C%20EXPLAIN%20ANALYZE%20%26%20Execution%20Plans "Share on Reddit")[Hacker News](http://news.ycombinator.com/submitlink?u=https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fpostgresql-query-optimization-indexes-explain&t=PostgreSQL%20Query%20Optimization%3A%20Indexes%2C%20EXPLAIN%20ANALYZE%20%26%20Execution%20Plans "Share on Hacker News")[Pinterest](https://pinterest.com/pin/create/button/?url=https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fpostgresql-query-optimization-indexes-explain&media=&description=Master%20PostgreSQL%20query%20optimization%20with%20practical%20examples.%20Learn%20EXPLAIN%20ANALYZE%20interpretation%2C%20effective%20index%20strategies%2C%20query%20rewriting%2C%20and%20connection%20pooling%20to%20identify%20and%20fix%20slow%20queries%20in%20production%20microservices. "Share on Pinterest")[Email](<mailto:?subject=PostgreSQL%20Query%20Optimization%3A%20Indexes%2C%20EXPLAIN%20ANALYZE%20%26%20Execution%20Plans&body=Check out this article: https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fpostgresql-query-optimization-indexes-explain>)

## Comments

## You might also enjoy

More posts on similar topics

[![Redis Caching Patterns: Cache-Aside, Write-Through & Cache Invalidation](/_astro/hero.Ck2oLF89_ZPiYlL.webp)](/codesnippets/post/redis-caching-patterns-architecture)

## [Redis Caching Patterns: Cache-Aside, Write-Through & Cache Invalidation](/codesnippets/post/redis-caching-patterns-architecture)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   [Backend](/codesnippets/categories/backend)
-   [Performance](/codesnippets/categories/performance)

Need to scale your backend without throwing money at servers? Start with Redis caching patterns. Most databases can handle hundreds of queries per second, but thousands? Your app slows to a crawl

[#Redis](/codesnippets/tags/redis)[#Caching](/codesnippets/tags/caching)[#Performance](/codesnippets/tags/performance)+6 tags

[read more](/codesnippets/post/redis-caching-patterns-architecture)

[![AWS DynamoDB CRUD Operations in Node.js with the AWS SDK v3](/_astro/hero.CceR-orf_Z2scRI0.webp)](/codesnippets/post/nodejs-dynamodb-crud-aws-sdk-v3)

## [AWS DynamoDB CRUD Operations in Node.js with the AWS SDK v3](/codesnippets/post/nodejs-dynamodb-crud-aws-sdk-v3)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   [Nodejs](/codesnippets/categories/nodejs)
-   [Aws](/codesnippets/categories/aws)
-   [Database](/codesnippets/categories/database)

Quick Tip Wrap the low-level DynamoDB client in a DynamoDBDocumentClient so you pass plain JavaScript objects in and get plain objects back, then guard your writes with ConditionExpression an

[#DynamoDB](/codesnippets/tags/dynamodb)[#Node.js](/codesnippets/tags/nodejs)[#AWS SDK v3](/codesnippets/tags/aws-sdk-v3)+3 tags

[read more](/codesnippets/post/nodejs-dynamodb-crud-aws-sdk-v3)

[![Python Async HTTP Requests with aiohttp: Fetch Multiple URLs Concurrently](/_astro/hero.DFXqyT8a_Zqhl7o.webp)](/codesnippets/post/python-async-http-aiohttp-concurrent-requests)

## [Python Async HTTP Requests with aiohttp: Fetch Multiple URLs Concurrently](/codesnippets/post/python-async-http-aiohttp-concurrent-requests)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   [Python](/codesnippets/categories/python)
-   [Async](/codesnippets/categories/async)
-   [Networking](/codesnippets/categories/networking)

Quick Tip Reuse one aiohttp session, fan your requests out with asyncio.gather, and cap them with a semaphore to fetch hundreds of URLs in the time one loop would take. The Problem \*\*The

[#Python](/codesnippets/tags/python)[#Aiohttp](/codesnippets/tags/aiohttp)[#Asyncio](/codesnippets/tags/asyncio)+3 tags

[read more](/codesnippets/post/python-async-http-aiohttp-concurrent-requests)

[![AWS EC2 Instance Management with Boto3: Start, Stop, and Query Instances](/_astro/hero.PnHlvJay_ZkFqWG.webp)](/codesnippets/post/aws-ec2-instance-management-boto3-python)

## [AWS EC2 Instance Management with Boto3: Start, Stop, and Query Instances](/codesnippets/post/aws-ec2-instance-management-boto3-python)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   [Cloud](/codesnippets/categories/cloud)
-   [Aws](/codesnippets/categories/aws)
-   [Devops](/codesnippets/categories/devops)
-   [Automation](/codesnippets/categories/automation)

If you've ever spent 20 minutes clicking through the AWS Console just to stop a handful of dev instances, you already know the pain. It's tedious, it doesn't scale, and one wrong click can ruin your a

[#AWS](/codesnippets/tags/aws)[#EC2](/codesnippets/tags/ec2)[#Boto3](/codesnippets/tags/boto3)+6 tags

[read more](/codesnippets/post/aws-ec2-instance-management-boto3-python)

[![Optimizing your python code with \_\_slots\_\_?](/_astro/hero.DP_vYsHU_gYDXn.webp)](/codesnippets/post/python-slots-optimization)

## [Optimizing your python code with \_\_slots\_\_?](/codesnippets/post/python-slots-optimization)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   [Python](/codesnippets/categories/python)
-   [Productivity](/codesnippets/categories/productivity)

Memory optimization with slots Understanding the problem Optimizing data models in big data workflows with slots In big data and MLOps workflows, you often work with massive

[#Python](/codesnippets/tags/python)[#MemoryOptimization](/codesnippets/tags/memoryoptimization)[#DataScience](/codesnippets/tags/datascience)+4 tags

[read more](/codesnippets/post/python-slots-optimization)

[![Multi-Environment Secret Management with HashiCorp Vault](/_astro/hero.B4H3tk7I_1BuPOM.webp)](/codesnippets/post/hashicorp-vault-multi-environment-secrets)

## [Multi-Environment Secret Management with HashiCorp Vault](/codesnippets/post/hashicorp-vault-multi-environment-secrets)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   [Security](/codesnippets/categories/security)
-   [Devops](/codesnippets/categories/devops)

Managing secrets safely across multiple environments with HashiCorp Vault Storing secrets in .env files, hardcoding them, or even using separate secret managers per environment creates security

[#Vault](/codesnippets/tags/vault)[#SecretsManagement](/codesnippets/tags/secretsmanagement)[#MultiEnvironment](/codesnippets/tags/multienvironment)+3 tags

[read more](/codesnippets/post/hashicorp-vault-multi-environment-secrets)

6 related posts
