A contractor who needs to fix an import, tune a query or migrate a table usually needs a database login to do it. The risk is rarely the contractor. It is the login itself: created in a hurry, broader than the task, pasted into an email, and still working six months after the invoice was paid.
The fix is a short routine. Decide whether direct access is needed at all, create a user that is scoped and already has an end date, send the password through a one-time secret link rather than a message that keeps copies, lock down the network path, and close the account when the work is done. This guide walks through each step with the exact commands where they help.
Does the contractor need direct database access?
Start with the task, not the request. "Fix the import" could mean reading one table, or it could mean write access to half the schema. Ask for the operation, the environment and the tables involved, then look for a cheaper way to give it.
- A staging database with a recent, sanitised copy covers most diagnostic and migration work with no exposure of live customer records.
- An application or admin API is often enough when the contractor needs to change data rather than schema.
- A read replica gives read-only analysis work a place to run without touching the primary.
If none of those fit and production access is unavoidable, write a one-line note of why. That note becomes the justification when someone audits the access later.
Create a user that is scoped and already expiring
Never hand over a shared login or an employee's credentials. A dedicated user is the thing that lets you see what the contractor did, restrict what they can reach, and remove them without affecting anyone else. Set the expiry on the user when you create it, so access ends even if you forget.
In PostgreSQL, a user that can only read two tables and stops working on a fixed date looks like this:
CREATE ROLE contractor_jo LOGIN PASSWORD 'generated-elsewhere'
VALID UNTIL '2026-11-08 18:00+00';
GRANT CONNECT ON DATABASE app TO contractor_jo;
GRANT USAGE ON SCHEMA public TO contractor_jo;
GRANT SELECT ON orders, order_items TO contractor_jo;
MySQL has CREATE USER ... PASSWORD EXPIRE INTERVAL 14 DAY, and
managed services such as RDS, Cloud SQL and Supabase let you do the
same from their consoles or with IAM-based short-lived tokens. Use
whichever your platform supports, and generate the password with a
password manager rather than typing one.
Grant the smallest set of permissions that completes the named task.
For a diagnostic job that means SELECT on specific tables. For a
migration it means write access to the objects that will change and
nothing else. Owner and superuser roles are never the right answer for
a temporary account.
How to send a temporary database login to a contractor
The password is the only part of the handoff that has to stay secret. The host, port, database name and username are useful to an attacker but not sufficient, so they can travel in an ordinary message. Keep the two apart.
- Verify the recipient through a channel you already trust, such as the contract email thread or a call. Lookalike addresses are a common way for a credential to go to the wrong inbox.
- Create a one-time secret link containing only the password. With LinkPilot the text is encrypted in your browser before it is stored, the stored copy is destroyed the first time the link is opened, and you can pick an expiry of one hour, 24 hours or seven days. Pro accounts can set a custom expiry, add a passphrase and see an audit timeline of when the link was opened.
- Send the link in the normal thread, with a one-line note of what it is for and when it expires. Do not include the username in the same message as the link.
- Send the connection details separately: host, port, database, username, and whether TLS is required. A second email or a ticket comment is fine, because nothing in it is secret on its own.
- Pass on a passphrase by a different channel if you set one, for example by text message or on a call.
- Ask the contractor to confirm that the link opened. If it says it has already been viewed and they did not open it, treat the password as exposed and rotate it.
A password manager's share feature is a reasonable alternative when the contractor is already in your vault. For a one-off engagement, a one-time link avoids creating an account just to hand over one value. The secret links vs password managers guide covers when each one fits.
Lock down the connection
A well-scoped user on an open port is still a problem. Three controls close most of the gap.
- Require TLS on the connection and tell the contractor to set
sslmode=requireor the equivalent in their client. Many clients fall back to plain text silently if you do not insist. - Restrict the source with an IP allowlist, a VPN or a bastion host. Allowlisting the contractor's address for the duration of the work is quick to set up and quick to remove.
- Share only what the task needs. The contractor does not need the internal network diagram, the other databases on the server or the admin console URL.
If your platform offers short-lived IAM tokens instead of static passwords, that is usually the better choice, and it removes the password handoff entirely.
Watch the account and close it out
Turn on authentication and query logging for the new user before the work starts, so you can compare what happened against what was agreed. Logins at odd hours or queries against unrelated tables are worth a question, not an accusation.
When the task ends, or the scope changes, do four things the same day:
- Drop or disable the user and confirm it can no longer connect.
- Remove the network allowance you added for them.
- Rotate any secret that travelled with the login, for example an application password that was in the same ticket.
- Record the handoff: who had access, to what, from when to when, and why. Keep the record, not the password.
A temporary login that is scoped, expiring, delivered once and closed on time is not a security exception. It is just how contractor access should work.