🚧 Under construction — VoTechWorks is being built. A free tech program — complimentary, as our commitment to get America working.
voTechWorksGrade 13 · a vocational technology learning center, by urbanicity
newSchoolWorks.com › VoTechWorks › Technology & Design › Data Management / Database Administration › Capstone Project: Integrated Database Administration System Build › Lesson 2
TEC-DATA86-10 · Lesson 2 · 72 clock hours · lab

Database Build: Schema, Security, Backup, and ETL Implementation

Objective. Students implement the approved schema in PostgreSQL, configure role-based access and TLS connections, schedule automated pg_dump backups with a tested restore procedure, and build an ETL pipeline using Python or pgAgent that loads and transforms data from two sources into the live database.

⚠ Pending professional review

This lesson, its worked examples and its practice questions has not yet been verified by an industry-certified professional or by a certification or approval body. It is a study draft and may contain errors. Do not use it as instructions for work on a job site or on live equipment. Always follow your instructor, your supervising professional, and current official references and regulations.

VoTechWorks program approval and accreditation are still in progress. Credentials are issued only by the certifying bodies named in each program, after their own exams.

Overview

This lab brings together every skill you have built during the program. You will implement a production-quality database system in PostgreSQL 15, covering schema deployment, role-based security, encrypted connections, automated backup with a tested restore, and an ETL pipeline that pulls data from two external sources. Work methodically: a mistake in security configuration or backup scheduling can have serious consequences in a real workplace.

Schema Implementation

Start by executing your approved DDL scripts in order: sequences and types first, then parent tables, then child tables that reference them. Every table must include primary key constraints, and every relationship must be enforced with a foreign key constraint. Add NOT NULL and CHECK constraints as specified in your design document. Create indexes on foreign key columns and on any column your query plan identified as a frequent filter. After DDL runs, verify the structure with `\d+ tablename` in psql.

Populate the database with at least 500 realistic rows. Use `COPY` to import the supplied CSV files, then run your Python script (with psycopg2) to generate synthetic rows that respect referential integrity — insert parent rows before child rows. After loading, run the instructor-provided SQL assertion queries. These queries use `EXCEPT`, `NOT EXISTS`, and aggregate checks to confirm that no orphan rows, duplicate primary keys, or out-of-range values exist. All assertions must return zero rows or the value zero to pass.

Role-Based Access Control and TLS

Create exactly the three required roles:

Grant column-level privileges with `GRANT SELECT (col1, col2) ON table TO role;` when a role must see some columns but not others (for example, masking salary from the analyst). Enable row-level security with `ALTER TABLE t ENABLE ROW LEVEL SECURITY;` and define policies using `CREATE POLICY`.

For encrypted connections, generate a self-signed certificate with OpenSSL (`openssl req` and `openssl x509`), place the server key and certificate where PostgreSQL expects them, set `ssl = on` in `postgresql.conf`, and update `pg_hba.conf` to require `scram-sha-256` over TLS for all remote connections. Refer to the CIS PostgreSQL Benchmark for the specific settings it recommends for authentication and logging — follow them as closely as your sandbox allows.

Document every configuration decision in a written security policy memo. Then perform a penetration check: log in as each role and attempt an operation that role is forbidden to perform (for example, `DELETE` as readonly_analyst). PostgreSQL should return a permission denied error. Record the results in your memo.

Automated Backup and Restore Drill

Schedule a `pg_dump` backup using cron (Linux) or Task Scheduler (Windows). A typical cron line for a nightly dump at 2 a.m. looks like:

```

0 2 * pg_dump -Fc -U postgres mydb > /backups/mydb_$(date +\%Y\%m\%d).dump

```

The `-Fc` flag writes a custom-format archive that `pg_restore` can use for selective or full restore. Store backups outside the database server's primary disk when possible.

The restore drill is not optional — it is a graded checkpoint. Drop the database (or create a fresh target), then run `pg_restore -d newdb /backups/mydb_YYYYMMDD.dump`. Confirm row counts match the pre-drop state. The restore must recover all data from within the prior 24 hours with zero data loss. Document the exact commands used and the time elapsed.

ETL Pipeline

Your pipeline extracts from two sources: a CSV flat file and a SQLite database. Use Python 3 with pandas for extraction and transformation, and psycopg2 for loading into PostgreSQL.

Extract: Read the CSV with `pd.read_csv()`. Open the SQLite source with `sqlite3` or `pandas.read_sql_query()`.

Transform: Apply documented rules — cast date strings to `datetime`, deduplicate on a business key with `drop_duplicates()`, fill or reject nulls according to your policy, and standardize text case. Log every rejected row to an error log file.

Load: Use a psycopg2 connection inside a transaction block (`BEGIN` / `COMMIT`). Write a row count to a transaction log before and after the load. If any `INSERT` raises an exception, roll back the entire batch and log the error; never leave the database in a partially loaded state.

Schedule the pipeline using cron or pgAgent. Validate by comparing the before-and-after row counts and reviewing the error log for unhandled exceptions. The loaded row count must fall within 5% of the expected count.

Safety and Professional Practices

Database administration involves physical and logical risks. On physical infrastructure: follow your organization's lockout/tagout and access-control procedures before working inside a server rack. Wear appropriate PPE (antistatic wrist strap) when handling storage media. On logical infrastructure: never store credentials in plain text in scripts — use environment variables or a secrets manager. Keep private keys for TLS certificates restricted to the postgres OS user (`chmod 600`). Test every change in the sandbox before applying it to any system that holds real data.

Key terms8

DDL (Data Definition Language)SQL statements such as CREATE, ALTER, and DROP that define or modify the structure of database objects like tables, indexes, and constraints.
Row-Level Security (RLS)A PostgreSQL feature that allows administrators to define policies controlling which rows a given role can view or modify, enforced automatically by the query engine.
pg_dump / pg_restorePostgreSQL utilities for creating logical backups of a database and restoring them; pg_dump exports the schema and data, and pg_restore recreates them in a target database.
ETL (Extract, Transform, Load)A data integration process that pulls data from source systems, applies cleaning and transformation rules, and loads the result into a target database.
pg_hba.confThe PostgreSQL host-based authentication configuration file that controls which hosts and users can connect, which databases they can access, and what authentication method is required.
TLS (Transport Layer Security)A cryptographic protocol that encrypts network traffic between a client and server; PostgreSQL uses TLS to protect credentials and data in transit.
pgAgentA job-scheduling agent for PostgreSQL, managed through pgAdmin, that can run SQL scripts or operating-system commands on a defined schedule without relying on OS-level cron.
SCRAM-SHA-256A secure password-authentication mechanism supported by PostgreSQL that protects credentials during the login handshake; recommended by the CIS PostgreSQL Benchmark over older methods such as md5.
In class: Write and execute DDL scripts to create all tables, constraints, indexes, and sequences; populate the database with a minimum of 500 realistic rows using a combination of supplied CSV imports and Python-generated synthetic data, verifying referential integrity with a set of provided SQL assertion queries. · Create at least three PostgreSQL roles (read-only analyst, data-entry operator, DBA) with column-level and row-level privileges where appropriate; configure pg_hba.conf for password authentication over TLS, document the security configuration in a written security policy memo, and perform a penetration check by attempting forbidden operations from each role account. · Build a Python or pgAgent ETL pipeline that extracts records from a CSV flat file and a SQLite source database, applies documented transformation rules (type casting, deduplication, null handling), loads results into the PostgreSQL target with transaction logging, and runs on a cron or pgAgent schedule; validate with a before-and-after row count and error log review.
Materials: PostgreSQL 15 on a local VM or cloud sandbox (AWS RDS free tier or Azure Database for PostgreSQL), Python 3 with psycopg2 and pandas, pgAdmin 4, OpenSSL for certificate generation, pg_dump / pg_restore, supplied CSV and SQLite source files, CIS PostgreSQL Benchmark (current version), pgAgent documentation
Check: Automated test suite (instructor-provided SQL scripts) must pass at least 18 of 20 integrity and security checks; restore drill must recover the database to a point-in-time within the prior 24 hours with zero data loss; ETL pipeline must complete without unhandled exceptions and load records within a 5% tolerance of the expected row count.

Practice check8

Answer each question, then check it. Nothing is recorded; this is your own practice.

Database design and data integrity
1. After importing CSV data with COPY, which SQL technique is most reliable for confirming that no child rows reference a non-existent parent key?
Security and access control
2. A readonly_analyst role must be able to query the employees table but must never see the salary column. Which PostgreSQL statement correctly implements this?
Security and access control
3. Which pg_hba.conf authentication method is recommended by the CIS PostgreSQL Benchmark for remote password-based connections over TLS?
Backup and recovery
4. You run pg_dump with the -Fc flag. What does this flag specify?
Backup and recovery
5. During the restore drill, you discover that the row count after pg_restore is 2% lower than before the drop. What is the most likely cause?
ETL and data integration
6. In your Python ETL pipeline, an INSERT into PostgreSQL raises an exception halfway through loading a batch. What is the correct action to maintain data integrity?
Security and access control
7. Row-level security (RLS) is enabled on the orders table. A data_entry_op user runs SELECT * FROM orders. Which rows will they see?
ETL and data integration
8. Your ETL pipeline loads an expected 1,000 rows. The acceptance criterion requires the result to be within 5% of the expected count. What is the minimum number of rows that must load for the pipeline to pass?
Record this lesson on my transcript. Sign in with your key and enrollment email to record lessons (enroll free if you have no key). This page stays open to read and practise.